Shoeisha Technology Media

CodeZine(コードジン)

記事種別から探す

Spread.ViewsとRaspberry Pi+ESP32搭載ボードNefry BTでインフルエンザ対策のBIツールを作る

IoT時代の救世主! SpreadJSで作るデータ可視化アプリ 第3回

  • LINEで送る
  • このエントリーをはてなブックマークに追加

目次

ブラウザへのデータのつなぎこみ

 MQTT.jsを利用して、Brokerに送られたデータをブラウザ側で受け取ります。クライアントサイドにSocket.ioの接続部分を追記します。

index.html
・
省略
・
・
    <script src="https://unpkg.com/mqtt@2.15.1/dist/mqtt.min.js"></script>
    <script>
        const client = mqtt.connect();
        client.subscribe("n0bisuke");

        client.on('message', (topic, payload) => {
           console.log(topic,payload.toString('utf-8'));
        });
    </script>
・
・
省略
・

 ブラウザで確認してみると、ブラウザのコンソールにセンサーの値が届いていることが分かります。

Spread.Viewsへのデータのつなぎこみ

 読み込んでいたsales_details_data.jsに以下のようなデータが入っています。

var data =[{"Salesperson":"Albertson, Kathy","May":"3947","June":"557","July":"3863","Aug":"1117","Sept":"8237","Oct":"8690"},{"Salesperson":"Allenson, Carol","May":"4411","June":"1042","July":"9355","Aug":"1100","Sept":"10185","Oct":"18749"},
・
・
(省略)
・

 このdata変数の形式に合わせて湿度、温度、CO2濃度のデータを入れ込みます。

index.html
<!doctype html>
<html style="height:100%;font-size:14px;">

<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" type="text/css" href="css/gc.spread.views.dataview.10.3.0.css">
    <script src="js/gc.spread.common.10.3.0.min.js" type="text/javascript"></script>
    <script src="js/gc.spread.views.dataview.10.3.0.min.js" type="text/javascript"></script>
    <script src="js/gc.spread.views.dataview.locale.ja-JP.10.3.0.min.js" type="text/javascript"></script>
    <script src="js/gc.spread.views.gridlayout.10.3.0.min.js" type="text/javascript"></script>
    <script src="js/gc.spread.views.sparkline.10.3.0.min.js" type="text/javascript"></script>
    <script src="js/license.js" type="text/javascript"></script>
    <script src="js/sales_details_data.js" type="text/javascript"></script>
    <script src="https://unpkg.com/mqtt@2.15.1/dist/mqtt.min.js"></script>
    <script>
        data = [
            {
                "環境データ":"湿度%",
                "6秒前":"75",
                "5秒前":"40",
                "4秒前":"23",
                "3秒前":"32",
                "2秒前":"51",
                "1秒前":"15"
            },
            {
                "環境データ":"温度℃",
                "6秒前":"75",
                "5秒前":"40",
                "4秒前":"23",
                "3秒前":"32",
                "2秒前":"51",
                "1秒前":"15"
            },
            {
                "環境データ":"CO2濃度_(×0.01)",
                "6秒前":"7.5",
                "5秒前":"4.0",
                "4秒前":"2.3",
                "3秒前":"3.2",
                "2秒前":"5.1",
                "1秒前":"1.5"
            },
        ];

        let humidity = [];
        let temperature = [];
        let co2 = [];

        const client = mqtt.connect();
        client.subscribe("n0bisuke");
        client.on('message', (topic, payload) => {
            console.log(topic,payload.toString('utf-8'));
            const json = JSON.parse(payload.toString('utf-8'));

            humidity.unshift(json.humidity);
            data[0]["6秒前"] = humidity[5];
            data[0]["5秒前"] = humidity[4];
            data[0]["4秒前"] = humidity[3];
            data[0]["3秒前"] = humidity[2];
            data[0]["2秒前"] = humidity[1];
            data[0]["1秒前"] = humidity[0];

            temperature.unshift(json.temperature);
            data[1]["6秒前"] = temperature[5];
            data[1]["5秒前"] = temperature[4];
            data[1]["4秒前"] = temperature[3];
            data[1]["3秒前"] = temperature[2];
            data[1]["2秒前"] = temperature[1];
            data[1]["1秒前"] = temperature[0];

            co2.unshift(json.co2 * 0.01); //値の範囲を調整
            data[2]["6秒前"] = co2[5];
            data[2]["5秒前"] = co2[4];
            data[2]["4秒前"] = co2[3];
            data[2]["3秒前"] = co2[2];
            data[2]["2秒前"] = co2[1];
            data[2]["1秒前"] = co2[0];

            dataView.invalidate();
            dataView = new GC.Spread.Views.DataView(
                document.getElementById('grid1'), 
                data,
                columns,
                new GC.Spread.Views.Plugins.GridLayout({
                    rowHeight: 100,
                    allowAsyncRender: isTouchDevice()
                })
            );

            const $humidityDom = document.getElementsByClassName("r0")[0];
            if(json.humidity < 30){
                $humidityDom.style.color = "red";
            }else{
                $humidityDom.style.color = "black";
            }
        });

    </script>
    <style>
        * {
            -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
        }
    </style>
</head>

<body style="margin:0;position:absolute;top:0;bottom:0;left:0;right:0;font-size:14px;user-select:none;-webkit-user-select: none;overflow:hidden;">
    <div id="grid1" style="height:100%"></div>
    <script>
        const lineSparklineSetting = {
            highMarkerColor: '#995D81',
            lowMarkerColor: '#FED766',
            markersColor: 'black',
            seriesColor: '#009FB7',
            showMarkers: true,
            showHigh: true,
            showLow: true,
            lineWeight: 2,
            minAxisType: 2,
            maxAxisType: 2,
            manualMax: 100,
            manualMin: 0
        };
        const columnSparklineSettings = {
            highMarkerColor: '#995D81',
            lowMarkerColor: '#FED766',
            markersColor: 'black',
            seriesColor: '#009FB7',
            showMarkers: true,
            showHigh: true,
            showLow: true,
            minAxisType: 2,
            maxAxisType: 2,
            manualMax: 100,
            manualMin: 0
        };
        const lineSparklineFormula = '=LINESPARKLINE("6秒前,5秒前,4秒前,3秒前,2秒前,1秒前", "", "' + JSON.stringify(lineSparklineSetting).replace(/\"/g, '') + '")';
        const columnSparklineFormula = '=COLUMNSPARKLINE("6秒前,5秒前,4秒前,3秒前,2秒前,1秒前", "", "' + JSON.stringify(columnSparklineSettings).replace(/\"/g, '') + '")';
        const smallDevice = screen.width <= 480;
        const colWidthSmall = smallDevice ? 125 : '*';
        const colWidthLarge = smallDevice ? 125 : '2*';

        const columns = [
            {
                id: '環境データ',
                caption: '環境データ',
                dataField: '環境データ',
                width: colWidthSmall
            }, {
                id: '6秒前',
                caption: '6秒前',
                dataField: '6秒前',
                dataType: 'number',
                format: '#.##'
            }, {
                id: '5秒前',
                caption: '5秒前',
                dataField: '5秒前',
                dataType: 'number',
                format: '#.##'
            }, {
                id: '4秒前',
                caption: '4秒前',
                dataField: '4秒前',
                dataType: 'number',
                format: '#.##'
            }, {
                id: '3秒前',
                caption: '3秒前.',
                dataField: '3秒前',
                dataType: 'number',
                format: '#.##'
            }, {
                id: '2秒前',
                caption: '2秒前.',
                dataField: '2秒前',
                dataType: 'number',
                format: '#.##'
            }, {
                id: '1秒前',
                caption: '1秒前.',
                dataField: '1秒前',
                dataType: 'number',
                format: '#.##'
            }, {
                id: 'trend',
                caption: 'LineSparkline',
                width: colWidthLarge,
                dataField: lineSparklineFormula
            }, {
                id: 'sales',
                caption: 'ColumnSparkline',
                width: colWidthLarge,
                dataField: columnSparklineFormula,
                visible: !smallDevice
            },
        ];

        const isTouchDevice = () => window.PointerEvent || window.MSPointerEvent || ('ontouchstart' in document.documentElement);

        dataView = new GC.Spread.Views.DataView(
            document.getElementById('grid1'), 
            data,
            columns,
            new GC.Spread.Views.Plugins.GridLayout({
                rowHeight: 100,
                allowAsyncRender: isTouchDevice()
            })
        );

        //focus data.view by default
        document.querySelector('#grid1').focus();
    </script>
</body>

</html>

 データは配列データになっていたので、その形式に合わせる形で作っています。

 データはデバイスごとに送信されてきてco2humidity-temperatureなどのトピック名ごとにイベントが発火します。データが送られて来たタイミングでグラフは再描画をし、閾値よりも湿度が低ければ赤い文字にしてアラートを出します。

動作の確認

 それでは実際にブラウザを確認してみます。

 このような感じで、温度と湿度、CO2濃度の値をリアルタイムに表示し、アラートするBIツールを作ることができました。

まとめ

 いかがでしたでしょうか。Spread.Viewsを利用することでIoTデータの可視化を行うことが出来ました。

 BIツールはオンラインサービスが多いですが、細かいところまで機能が充実していない、かといって一からグラフなどの実装を自分たちでやるのはタスクが多すぎる。そういった場合にSpread.Viewsを使って自作BIツールを作るのは選択肢としてはアリだと思います。

 また今回は分かりやすさを優先し簡単なデータ例でご紹介しましたが、使用電気料、物流データ、入退出データなどを利用したBIツールにもカスタマイズできます。

 皆さんも是非Spread.Viewsを使ってお手軽データ可視化を試してみて下さい。

 それでは!



  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • 菅原のびすけ(dotstudio株式会社)(スガワラ ノビスケ)

     日本最大規模のIoTコミュニティ「IoTLT」主催。岩手県立大学大学院ソフトウェア情報学研究科を卒業後、株式会社LIGでWebエンジニアとして入社し、Web開発に携わる。2016年にdotstudio株式会社を立ち上げ、今はIoT領域を中心に活動している。JavaScript Roboticsコミ...

バックナンバー

連載:IoT時代の救世主! SpreadJSで作るデータ可視化アプリ
All contents copyright © 2005-2018 Shoeisha Co., Ltd. All rights reserved. ver.1.5