ハードウェア(IoT機器)とkintoneの連携Tipsはすでにいくつかありますが、そのほとんどがハードウェア側の知識も必要なことが多いです。
ハード側で利用する言語もCやJavaなどWebとは異なる言語を利用することが多いため、その点でもWebエンジニアからは敷居が高かったりします。
obniz(オブナイズ)
はJavaScriptでプログラムを書くことができ、Webの知識でハードウェアの操作が可能なデバイス(IoTプラットフォーム)です。
JavaScriptでカスタマイズできるkintoneとはいろいろと相性が良く、今回はそのobnizとkintoneを連携させて 物理ボタンクイズ を実現してみます。
現実とコンピューター世界をつなぐデバイスやクラウドを提供しているオールインワンのIoTプラットフォームです。
obniz boardと呼ばれるデバイスの他に、obniz OSという市販の開発デバイスにインストールすることでobnizとして扱うことが可能なOSも提供しています。
特徴はなんといっても クラウドで動かすことができる ところです。
従来の「デバイスにプログラムを書き込む」タイプではなく、obnizはプログラムをクラウドに配置します。
配置したプログラムはWi-Fi経由でobnizに読み取られ、動作するというしくみになっています。
そのためWebエンジニアでも簡単にハードウェアをいじることができるのでとてもおすすめです!
obnizに接続した物理ボタンを押すと、ブラウザーが切り替わるしくみでクイズを作っています。
ポイントは obnizのプログラムをkintone上にアップしている 点です。
obnizのプログラムはクラウド上に配置すればよく、クラウド製品のkintone上に配置しても動かすことができます。
さらに、kintone上に配置することでkintoneが用意しているkintone JavaScript APIも一緒に利用できるため、かなり連携がしやすくなります!
まるでマウス操作をしているかのように、物理ボタンでkintoneが操作できます!
また、同アプリに正誤率を貯めるようにもしているので、あとで「どの問題が難しいか」なども把握できます。
kintoneの設定
固定リンクがコピーされました
クイズ出題アプリ、クイズマスターアプリの2つのアプリを用意しています 。
正誤の情報を登録するアプリです。
アプリの構成は以下のようになっています。
フィールド名 |
フィールドタイプ |
フィールドコード |
クイズレコードURL |
文字列(1行) |
url |
問題 |
文字列(1行) |
question |
正誤 |
ドロップダウン |
result |
作成日時 |
作成日時 |
CreateTime |
さらにこちらのアプリには、カスタマイズビューとして「出題ビュー」「正解ビュー」「不正解ビュー」を作成しています。
カスタマイズビューのHTMLについては
プログラム
で説明します。
クイズマスターアプリ
固定リンクがコピーされました
アプリの構成は以下のようになっています。
フィールド名 |
フィールドタイプ |
フィールドコード |
問題 |
文字列(1行) |
question |
選択肢1 |
文字列(1行) |
choice1 |
選択肢2 |
文字列(1行) |
choice2 |
選択肢3 |
文字列(1行) |
choice3 |
選択肢4 |
文字列(1行) |
choice4 |
正解 |
文字列(1行) |
answer |
本当は正解フィールドはラジオボタン等の選択式にしたかったですが、今回はコードのわかりやすさ重視で文字列1行フィールドとしています。
今回作成したJavaScript、CSS、カスタマイズビュー用HTMLは以下となります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
/*
* kintone-obniz sample program
* Copyright (c) 2019 Cybozu
*
* Licensed under the MIT License
* https://opensource.org/license/mit/
*/
(() => {
'use strict';
// クイズマスタアプリのアプリID
const quizAppId = '{YOUR_QUIZ_MASTER_APP_ID}';
// クイズ出題アプリ(自身)のアプリID
const thisAppId = kintone.app.getId();
// 出題・正解・不正解のカスタマイズビューID
const view = {
index: '{YOUR_INDEX_VIEW_ID}',
success: '{YOUR_SUCCESS_VIEWP_ID}',
fail: '{YOUR_FAIL_VIEW_ID}',
};
// obnizのID
const obnizId = '{YOUR_OBNIZ_ID}';
// クイズの正誤をレコード登録する関数
const postRecord = (RECORD, TEXT) => {
const body = {
app: thisAppId,
record: {
url: {
value: `https://${document.domain}/k/${quizAppId}/show#record=${RECORD.$id.value}`,
},
question: {
value: RECORD.question.value,
},
result: {
value: TEXT,
},
}
};
return kintone.api(kintone.api.url('/k/v1/record', true), 'POST', body)
.then(resp => console.log('レコードの登録成功')).catch(err => window.alert('レコードの登録失敗'));
};
// クイズマスタアプリからクイズ内容を取得する関数
const getQuizRecords = () => {
return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', {app: quizAppId})
.then(resp => console.log('レコード取得成功')).catch(err => window.alert('レコードの取得失敗'));
};
// クイズ出題ビューを開いたとき
kintone.events.on('app.record.index.show', e => {
if (e.viewId !== view.index) return;
const obniz = new Obniz(obnizId);
obniz.onconnect = async () => {
obniz.display.clear();
// クイズ内容のレコードを取得
const QuizData = await getQuizRecords();
// クイズ内容の中からランダムで1つ表示
const random = Math.floor(Math.random() * QuizData.length);
const answer = QuizData[random].answer.value;
// 問題文を表示するDOM
const $questionTextArea = $('.question-text');
// 解答の選択肢を表示するDOM
const $answerTextArea = $('.answer-text');
// それぞれのDOMにテキスト表示
$questionTextArea.text(QuizData[random].question.value);
$answerTextArea.each((index, val) => {
$(val).text(QuizData[random]['choice' + (index + 1)].value);
});
// obnizのボタンの設定
const buttons = [
obniz.wired('Button', {signal: 0, gnd: 1}),
obniz.wired('Button', {signal: 2, gnd: 3}),
obniz.wired('Button', {signal: 4, gnd: 5}),
obniz.wired('Button', {signal: 6, gnd: 7}),
];
// それぞれのボタンにイベントをつける
buttons.forEach((btn, index) => {
btn.onchange = async pressed => {
if (!pressed) return;
// 枠の色を変える
$($answerTextArea[index]).css({
borderColor: '#ffff00'
});
// 正解なら「正解」とレコード登録して、正解ビューへ遷移
// 不正解なら「不正解」とレコード登録して、不正解ビューへ遷移
if (answer === QuizData[random]['choice' + (index + 1)].value) {
await postRecord(QuizData[random], '正解');
location.href = `/k/${thisAppId}/?view=${view.success}`;
} else {
await postRecord(QuizData[random], '不正解');
location.href = `/k/${thisAppId}/?view=${view.fail}`;
}
};
});
};
});
// 正解・不正解ビューを開いたとき
kintone.events.on('app.record.index.show', e => {
if (e.viewId !== view.success && e.viewId !== view.fail) return;
// 3秒後にクイズ出題ビューへ遷移
setTimeout(() => {
location.href = `/k/${thisAppId}/?view=${view.index}`;
}, 3000);
});
})();
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
/*
* kintone-obniz sample program
* Copyright (c) 2019 Cybozu
*
* Licensed under the MIT License
* https://opensource.org/license/mit/
*/
/* index html */
#myDiv {
text-align: center;
font-weight: bold;
font-size: 20px;
}
.question-frame,
.answer-frame {
margin: 2%;
}
.question-top {
font-size: 50px;
}
.question-text {
font-size: 40px;
}
.answer {
margin: 0 auto;
}
.answer tr {
height: 200px;
}
.answer tr td div {
display: inline-block;
border: solid 8px #ccc;
word-break: break-all;
height: 100px;
vertical-align: middle;
display: table-cell;
padding: 0 10% 0 20%;
width: 250px;
}
.td-space {
width: 80px;
}
/* success/fail html */
#resultDiv {
text-align: center;
}
#resultDiv img {
width: 50%;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
<!--
* kintone-obniz sample program
* Copyright (c) 2019 Cybozu
*
* Licensed under the MIT License
* https://opensource.org/license/mit/
-->
<div id="myDiv">
<div class="question-frame">
<span class="question-top">Q. </span>
<span class="question-text"></span>
</div>
<div class="answer-frame">
<table class="answer">
<tr>
<td><img class="answer-img" src="{ボタンAの画像のURLなど}"></td>
<td><div class="answer-text"></div></td>
<td class="td-space"></td>
<td><img class="answer-img" src="{ボタンBの画像のURLなど}"></td>
<td><div class="answer-text"></div></td>
</tr>
<tr>
<td><img class="answer-img" src="{ボタンCの画像のURLなど}"></td>
<td><div class="answer-text"></div></td>
<td class="td-space"></td>
<td><img class="answer-img" src="{ボタンDの画像のURLなど}"></td>
<td><div class="answer-text"></div></td>
</tr>
</table>
</div>
</div>
|
1
2
3
4
5
6
7
8
9
10
11
|
<!--
* kintone-obniz sample program
* Copyright (c) 2019 Cybozu
*
* Licensed under the MIT License
* https://opensource.org/license/mit/
-->
<div id="resultDiv">
<img src="{正解画面に挿入する画像のURLなど}">
</div>
|
1
2
3
4
5
6
7
8
9
10
11
|
<!--
* kintone-obniz sample program
* Copyright (c) 2019 Cybozu
*
* Licensed under the MIT License
* https://opensource.org/license/mit/
-->
<div id="resultDiv">
<img src="{不正解画面に挿入する画像のURLなど}">
</div>
|
jQueryとobnizのライブラリ、上記script.jsを以下の順番で配置します。
順番 |
詳細 |
URL / JSファイル |
1 |
jQuery |
https://js.cybozu.com/jquery/3.4.1/jquery.min.js |
2 |
obnizのライブラリ |
https://unpkg.com/obniz@2.0.3/obniz.js |
3 |
上記JSファイル |
script.js |
まるでJavaScriptのライブラリのようにobniz(ハードウェア)が操作できます!
obniz側のプログラム次第ではLEDを光らせたり、サーボモータを動かしたりできるので、kintoneとの連携の夢が広がりますね!