前回に、「[3]会議室使用状況センサーの自作 〜ArduinoでESP8266のプログラミング〜」でIoTデバイスのプログラミングを行いました。
これまでIoTセンサーの製作、IoTサーバのセットアップ、IoTデバイスのプログラミングが完了し、今回は「Javascriptを使ってIoTセンサーの状態を表示するWebサイトの作成」を行います。
1. 会議室使用状況センサーの実装構想(振り返り)
目標は、会議室に自作したIoT人感センサーを設置して、センサー状態を会社のスケジューラーであるサイボウズガルーンに表示させる。
実現方法としては以下のように考えて作ります。
1. マイコンと人感センサーを使って電子工作(IoTデバイス製作)
2. センサーデータの保管先IoTサーバのセットアップ
3. IoTデバイスのプログラミング
4. JavaScriptで簡単なページを作成して、IoTサーバの情報を取得し表示←今回はこちらの話
5. サイボウズガルーンに設定
2. データ取得のための基本的なAPI
今回、サイボウズガルーンで表示させるので、JavaScriptを使ってコーディングを行っていきます。
また、milkcocoaからデータを呼び出すため使用する主なオブジェクトとメソッドは、以下のものになります。
全体のAPIリファレンスは、milkcocoaで公開されているサイト見ていただければと思います。
今回使用するmilkcocoa APIのオブジェクト・メソッド一覧
milkcocoa APIを使用するには、まずScriptタグを使用することで利用できます。
# | オブジェクト/メソッド | 機能詳細 |
1 | connectWithApiKey() | API Keyを指定しデータストアに接続 |
2 | dataStore() | データストアからデータを取得 |
2-1 | .history() | 期間や個数を指定してデータを取得 |
2-1-1 | .sort() | データ取得する順番指定 |
2-1-2 | .size() | データ取得する個数指定 |
2-1-3 | .span() | データ取得する期間指定 |
2-1-4 | .on() | イベントハンドラ指定 |
2-1-5 | .run() | データ取得の実行 |
1. connectWithApiKey()
データストアに接続するため、ホスト、API Key、API Secret値を指定します。
この値は前回「会議室使用状況をセンサーで確認する 〜その3〜」で設定した値と同じものです。
例)connectWithApiKey(‘BBBBB.mlkcca.com’, ‘CCCCC’, ‘DDDDD’)
2. dataStore()
ここで指定したデータストアからデータを取得します。
こちらの値も前回のブログで指定した値となります。
例)dataStore(‘EEEEE’)
またdataStore()には以下のようなメソッドを使い、データを取得します。
2-1. history()
history()オブジェクトは、データ取得する個数や期間を指定して取得するメソッドが用意されています。
今回は、2-1-1〜5に記載した5つのメソッドを使用してデータ取得を行なっています。
3. Bassからのデータ取得の仕組み
IoTセンサー側では、以下のようにステータス更新(MQTTでPush)を行ないました。
- センサーがONの状態が6秒続けば、IN USEステータスをBaasに保管
- センサーがOFFの状態が30秒続けば、VacantステータスをBaasに保管
- ステータスに変化がない場合はセンサーの死活監視用として、60分おきに現状ステータスをBaasに保管
Webサイト側では、以下のような設定でステータスを取得します。
- 過去10件分のデータを取得
- かつ、過去70分間のデータを取得
今回4つのIoTセンサーからのデータをPushしていますが、センサーのON/OFFが多い場合またはセンサー数が多い場合は、過去10件分を状況に合わせて調整して良いかと思います。
これを調整しないと「Out of Service」の表示が出てくる可能性があります。
4. 検証プログラム
サイボウズにアップする前に、一旦ローカルでHTMLを作成して、表示の確認をしてみます。
4-1. 環境状況により変更すべき点
4-1-1. API Key等の設定
以下のAPI Key等記載している箇所は、前回の取得した情報に書き換えてください。
<!– milkcocoaのセットアップ –>
var milkcocoa = MilkCocoa.connectWithApiKey('BBBBB', 'CCCCC', 'DDDDD');
var dsh = milkcocoa.dataStore('EEEEE').history();
4-1-2. 会議室のレイアウト図
会議室のレイアウトに合わせて、センサーのステータスを表示させるためイメージ図を用意しておきます。
ファイル名と配置場所は以下のようにしています。
<!- Conf. area map ->
<div class="content-wrap">
<div style="width: 400px">
<img src="./confmap.png" alt="topimg">
イメージ図は以下のようなものです。
4-1-3. サイボウズ会議室とのスケジュールリンク
ステータス表示されている会議室の枠にサイボウズの会議室スケジュールリンクをセットして、予定を確認できるようにしています。
<!- 会議室A ->
<a href="http://garoon.xxxx.co.jp/scripts/cbgrn/grn.exe/schedule/personal_day?uid=f3&gid=f" target="_blank">
<!- Garoonでは、top-7,Left-8px ->
<div id="会議室A" class="Label_OOS" style="top:51px; left:58px;">
<span style="font-size:150%">会議室A</span><br />
<span id="会議室A1"></span><br />
<span id="会議室A2">Out of</span><br />
<span id="会議室A3">service</span>
</div></a>
4-2. コード全体
環境状況に合わせて下記のコードを修正する必要がありますが、全体コードは以下の通りです。
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<style type="text/css">
.Label_Use {
position: absolute;
padding: 5px 5px;
width: 80px;
height: 70px;
text-align: center;
color: white;
font-family: monospace;
background: #0000cd;
}
.Label_Vacant {
position: absolute;
padding: 5px 5px;
width: 80px;
height: 70px;
text-align: center;
color: white;
font-family: monospace;
background: #32cd32;
}
.Label_OOS {
position: absolute;
padding: 5px 5px;
width: 80px;
height: 70px;
text-align: center;
color: white;
font-family: monospace;
background: #555555;
}
</style>
<!- Load Javascript files ->
<script src="https://code.jquery.com/jquery-1.12.1.min.js"></script>
<script src="https://cdn.mlkcca.com/v0.6.0/milkcocoa.js"></script>
<!- Conf. area map ->
<div class="content-wrap">
<div style="width: 400px">
<img src="./confmap.png" alt="topimg">
<!- 会議室A ->
<a href="http://garoon.xxxx.co.jp/scripts/cbgrn/grn.exe/schedule/personal_day?uid=f3&gid=f" target="_blank">
<!- Garoonでは、top-7,Left-8px ->
<div id="会議室A" class="Label_OOS" style="top:51px; left:58px;">
<span style="font-size:150%">会議室A</span><br />
<span id="会議室A1"></span><br />
<span id="会議室A2">Out of</span><br />
<span id="会議室A3">service</span>
</div></a>
<!- 会議室B ->
<a href="http://garoon.xxxx.co.jp/scripts/cbgrn/grn.exe/schedule/personal_day?uid=f2&gid=f" target="_blank">
<div id="会議室B" class="Label_OOS" style="top:51px; left:162px;">
<span style="font-size:150%">会議室B</span><br />
<span id="会議室B1"></span><br />
<span id="会議室B2">Out of</span><br />
<span id="会議室B3">service</span>
</div></a>
<!- 会議室C ->
<a href="http://garoon.xxxx.co.jp/scripts/cbgrn/grn.exe/schedule/personal_day?uid=f4&gid=f" target="_blank">
<div id="会議室C" class="Label_OOS" style="top:164px; left:58px;">
<span style="font-size:150%">会議室C</span><br />
<span id="会議室C1"></span><br />
<span id="会議室C2">Out of</span><br />
<span id="会議室C3">service</span>
</div></a>
<!- 会議室D ->
<a href="http://garoon.xxxx.co.jp/scripts/cbgrn/grn.exe/schedule/personal_day?uid=f5&gid=f" target="_blank">
<div id="会議室D" class="Label_OOS" style="top:164px; left:162px;">
<span style="font-size:150%">会議室D</span><br />
<span id="会議室D1"></span><br />
<span id="会議室D2">Out of</span><br />
<span id="会議室D3">service</span>
</div></a>
</div>
</div>
<!– milkcocoaのセットアップ –>
<script type="text/javascript">
var milkcocoa = MilkCocoa.connectWithApiKey('BBBBB', 'CCCCC', 'DDDDD');
var dsh = milkcocoa.dataStore('EEEEE').history();
var room = "";
var stat_room = "";
var one_hour = 70 * 60 * 1000; // 70分のシリアル値取得
var today = new Date().getTime();
var pasttime = today - one_hour;
dsh.sort('desc');
dsh.size(10);
dsh.span(pasttime,today);
dsh.on('data', function(datas) {
datas.forEach(function(data) {
room = data.value.RMname;
stat_room = data.value.stat;
(stat_room=="Vacant")?document.getElementById(room).className="Label_Vacant":(stat_room=="IN USE")?document.getElementById(room).className="Label_Use":document.getElementById(room).className="Label_OOS";
$('#'+room+'1').text(stat_room);
$('#'+room+'2').text(Serial2Date(data.timestamp));
$('#'+room+'3').text(Serial2Time(data.timestamp));
});
});
dsh.run();
function Serial2Date(timestamp){
var d = new Date(timestamp);
var year = d.getFullYear();
var month = d.getMonth() + 1;
var day = d.getDate();
return ( year + '/' + month + '/' + day);
}
function Serial2Time(timestamp){
var d = new Date(timestamp);
var hour = ( d.getHours() < 10 ) ? '0' + d.getHours() : d.getHours();
var min = ( d.getMinutes() < 10 ) ? '0' + d.getMinutes() : d.getMinutes();
var sec = ( d.getSeconds() < 10 ) ? '0' + d.getSeconds() : d.getSeconds();
return ( hour + ':' + min + ':' + sec );
}
</script>
</body>
</html>
4-3. HTML表示イメージ
こちらのHTMLをブラウザで表示すると以下のように表示されます。
各ステータスは以下のようにしました。
ステータス | カラー | 状態 |
「Out of Service」 | グレー | センサーが機能していない状態 |
「LinkUp」 | グレー | センサーが起動して、まだステータスが更新されていない状態 |
「IN USE」 | ブルー | 会議室が使用中 |
「Vacant」 | グリーン | 会議室が未使用 |
5. サイボウズガルーンに設定
かなり長くなってしまいましたが、サイボウズガルーンへの反映は次回「サイボウズガルーンに設定」で掲載し、今回のプログラミングは完了となります。
コメント