★本系列文章已集結成冊,和系列文不同的是:
- 本書使用大量的圖解來說明LED系列、多種感測器等原理。
- 補足系列文程式碼的解說,增加逐行程式碼的詳細解說!
- 全彩的書籍,用圖解的方式,讓讀者來理解Johnny-Five各種API的功能與效果,讓你不會只讀文字看到想睡覺而學不起來。
歡迎大家做出自己想要的玩具,為了樂趣而學習,讓學習變成你的樂趣!ヽ(・×・´)ゞ
讓Arduino也能用JavaScript創造出屬於自己的作品!★購書連結-天瓏網路書局:
https://www.tenlong.com.tw/products/9789864345328《IoT沒那麼難!新手用 JavaScript 入門做自己的玩具!(iT邦幫忙鐵人賽系列書)》
博客來、金石堂、momo、誠品、PChome、讀冊,均有販售喔!─=≡Σ((( つ•̀ω•́)つ
ISBN:9789864345328
本文先聲明為教學用途,不負任何責任(欸?
昨天主要講解PIR的工作原理和測試、實驗一下,
今天要來作一點小應用! ヽ(・×・´)ゞ
下音樂 again ~
登登楞登~登登~ (多拉A夢的音效)**
※使用前請詳閱公開說明書,請保證工作進度超前在使用本產品,本產品不負被抓包相關責任。(被打)
謎之音:這有什麼好做的....不就人體偵測嗎...ಠಠ
本魯:當然要加一點花樣騙騙人啊...欸不對...應該是發揮才能才對 ...
因為我的 PIR Sensor 是從 Webduino 買豪華套件包來的,
發現我的 PIR Sensor 不能調觸發模式,就不能做更好玩的應用了...嗚嗚QQ...(以後會改善的Orz
所以既然不能調觸發模式,那就想別的方法吧~
又是靈光一閃過!(✪ω✪)
科技始於人性,人性始於墮性(?
像我們開發者整天坐在辦公室,需求一直改一直改,不如等到完全定案之後再開發
等待的時間又要假裝有在上班,實際上我就不說了...XD
所以研發了這個東西!
當薪水小偷可以不用很緊張,老闆快走過來時即時開啟 Stack overflow 或是 MDN 假裝在查Doc!(´≖◞౪◟≖)
當老闆快要走到我的位子的時候 → 人體感測器感測到老闆 → motionstart
事件 → 透過 Socket 給前端資料 → 紀錄資料並開啟預設「看起來認真上班的網頁」。
恩~ 計画通り!ᕙ(˵ ಠ ਊ ಠ ˵)ᕗ
接下來跟著我一起浪費才能吧~ヽ(・×・´)ゞ
謎之音:又來了....(ㆆᴗㆆ)
首先補充一下昨天的沒有仔細說到的 Events 部分
觸發 Johnny-Five Motion
物件後,會 retrun 資料物件
{
// 時間戳
timestamp: 1570416994150,
// 偵測動作狀態,若有動作則返回布林值 `true` , 反則返回布林值 `false`
detectedMotion: true,
// 是否校準,已校準則返回布林值 `true` , 反則返回布林值 `false`
isCalibrated: true
}
這邊要注意的 Johnny-Five 返回的 timestamp
是13位數的時間戳
13 位數的時間戳精度為「毫秒」
10 位數的時間戳精度則是「秒」
但 JavaScript 處理的是10位的時間戳,要怎麼辦呢?
本魯宅:因為現在用不到毫秒等級那麼細的時間戳,只好切掉了!(≖_≖)✧
使用 Javascript 的字串處理 substr 函式 ,截取從 0~10 的字元就好
// 返回一個從指定位置開始的指定長度的子字串
String.substr(指定開始位置,截取長度);
MDN - String.prototype.substr()
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr
但這邊又要注意了!!
因為 Johnny-Five 回傳的 timestamp 型別是 Number
而不是 String
,
直接用 substr()
函式擷取字元的話,會因為型別不對而報錯!
motion.on('motionstart', function(data) {
timestamp = data.timestamp;
console.log(typeof timestamp); // Number
});
substr()
因為型別不對而報錯!
所以我們要把 Johnny-Five 吐出的時間戳轉為字串型別(String),在用 substr() 截取時間戳字串!
測試看看!
這樣就可以取出時間戳來轉換成人讀的時間了~(ง๑ •̀_•́)ง
剛剛提到物件中, Johnny-Five 還會返回 isCalibrated
和 detectedMotion
物件,這兩個物件的值都是布林值 true
/ false
。
我們先了解物件的意義:
isCalibrated
isCalibrated
和 motion.on('calibrated', function() { });
一樣都只會在一開始做一次,當第一次發生目標物移動時則偵測訊號成功,isCalibrated
返回就會 true
值;
之後觸發的 motion 動作,不管是 start 還是 end 的都會看到 isCalibrated
值都是 true
。
detectedMotion
當目標物有移動動作,PIR Sensor 偵測到時便會回傳 detectedMotion
為ture
,就字面上的意思來說就是「偵測到動作了!」;
當目標物停止移動動作,會回傳 detectedMotion
為false
,意思來說就是「剛剛的偵測到的動作停止了!」。
但每個觸發不同的事件,回傳的也會不一樣,
'calibrated'
校準事件
function data 不會回傳物件值,事件'calibrated'
就表示只是一個狀態!
motion.on('calibrated', function(data) {
console.log(data);
console.log('calibrated');
});
'motionstart' 偵測到動作事件
motion.on('motionstart', function(data) {
console.log(data);
console.log('motionstart');
});
此事件會 function data 返回
{
timestamp: 1570420021897,
detectedMotion: true,
isCalibrated: true
}
'motionend' 沒有偵測到動作了
motion.on('motionend', function(data) {
console.log(data);
console.log('motionstart');
});
此事件會 function data 返回
{
timestamp: 1570420021897,
detectedMotion: false,
isCalibrated: true
}
講好多....終於要來實作啦~
程式碼很簡單,我們透過JavaScript window.open()
事件來實現這個應用~(ง๑ •̀_•́)ง
var io = require('socket.io');
var express = require('express');
var five = require('johnny-five');
var board = new five.Board();
var app = express();
app.use(express.static('www'));
var server = app.listen(3000, function() {
console.log('connected!');
});
var sio = io(server);
board.on('ready', function() {
var motion = new five.Motion({
pin: '7',
freq: 250,
});
sio.on('connection', function(socket) {
motion.on('calibrated', function() {
//PIR Sensor Ready
console.log('準備好啦!');
});
motion.on('motionstart', function(data) {
// 偵測到有生物在動,觸發事件
console.log('偵測到老闆!');
socket.emit('startData', {
// socket 傳送資料給前端
isAction: data,
});
});
});
});
HTML 網頁就隨便裝飾一下,目的只是要開啟 Socket 連線而已~
<body>
<div class="container">
<h2 class="p-5">老 闆 移 動 偵 測</h2>
</div>
<nav class="navbar navbar-light bg-light fixed-bottom">
IoT沒那麼難!新手用JavaScript入門做自己的玩具 系列文 Tzeng,Ying-Chi
</nav>
<script src="/socket.io/socket.io.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="index.js"></script>
</body>
var socket = io.connect();
socket.on('startData', function(data) {
//接收到偵測資料
motionData = data.isAction;
// 時間戳處理
// 先處理數字轉字串 motionData.timestamp + ''
// 接下來分割 10位數時間戳
// 在用 parseInt() 函式轉回數字型別
timestamp = parseInt((motionData.timestamp + '').substr(0, 10));
// 取得是否偵測到動作
isMotion = motionData.detectedMotion;
// 轉換成人看的時間格式
humanCanReadTime = getTime(timestamp);
if (isMotion === true) {
// 當老闆來時,在新分頁打開裝認真的網頁
window.open(
'https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Array',
'_blank',
);
// 印出時間點
$('.container').append(
'<div class="alert alert-danger boss-alert" role="alert">老闆出現於 <span class="time">' +
humanCanReadTime +
'</span> !</div>',
);
}
// 時間戳格式轉換
function getTime(timestamp) {
var time = new Date(timestamp * 1000);
var h = time.getHours();
var min = time.getMinutes();
var s = time.getSeconds();
h = checkTime(h);
min = checkTime(min);
s = checkTime(s);
timeStr = h + ':' + min + ' ' + s + '秒';
return timeStr;
}
function checkTime(i) {
if (i < 10) {
i = '0' + i;
} // add zero in front of numbers < 10
return i;
}
});
來Demo看看吧!!ヽ(・×・´)ゞ
Demo
想必大家都知道要如何寫出這麼棒的應用了吧~(才沒有!!
那今天就先到這囉~謝謝收看啦~─=≡Σ((( つ•̀ω•́)つ
我絕對不是會用這種東西的工程師!不要誤會我 XDDD
本系列的程式碼皆會上傳到 GitHub 上開源
2019ironman-JS-IoT :
https://github.com/tinatyc/2019ironman-JS-IoT
喜歡按個星星吧~乾蝦乾蝦<(_ _)>
團隊系列文:
CSScoke - 金魚都能懂的這個網頁畫面怎麼切 - 金魚都能懂了你還怕學不會嗎
Hina Hina - 陣列大亂鬥
阿斬 - Python 程式交易 30 天新手入門
Clarence - LINE bot 好好玩 30 天玩轉 LINE API
塔塔默 - 用Python開發的網頁不能放到Github上?Lektor說可以!!
Vita Ora - 好 Js 不學嗎 !? JavaScript 入門中的入門。
同步連載於blogger-King 學習前端之人生