牛人教你使用Node.js和Twilio實(shí)現(xiàn)手機(jī)控制門鎖
試想一下,如果你忘了帶鑰匙,但你帶手機(jī)了,你就可以打開(kāi)門鎖?;蛘?,你還在往家趕,可你的朋友已經(jīng)到你家門口,你通過(guò)手機(jī)遠(yuǎn)程把家門打開(kāi),讓朋友先自己進(jìn)去看會(huì)兒電視。這不是科幻,也不需要多先進(jìn)的設(shè)備,而是自己動(dòng)手開(kāi)發(fā)出來(lái)的。
本文是基于我在波蘭的Makerland大會(huì)上的一次研討演講。這篇文章將會(huì)指導(dǎo)你如何通過(guò)手機(jī)控制你家的門鎖,而且是在不需要弄壞或改造門鎖的情況下實(shí)現(xiàn)。我們需要使用一個(gè)微控制器(Arduino Uno),一個(gè)電機(jī),和Node.js,用它們來(lái)實(shí)現(xiàn)通過(guò)短信遠(yuǎn)程開(kāi)鎖和關(guān)鎖。我是受到了Twilio-powered Lockitron的啟發(fā)。
步驟1:設(shè)備
部件
1. 一把門鎖
2. 膠帶,紙板
3. 電機(jī)(我使用的是HS-322HD)
4. 微控制器(Arduino Uno) + 轉(zhuǎn)接線
準(zhǔn)備
1. 從http://arduino.cc/en/Main/Software下載和安裝Arduino IDE。
2. 從http://nodejs.org/獲取并安裝
3. 從https://ngrok.com/download下載并安裝 ngrok (一個(gè)內(nèi)網(wǎng)穿透程序)
我 將使用Arduino IDE寫代碼并上傳到往微控制器里。我使用node.js腳本語(yǔ)言來(lái)和Arduino微處理器進(jìn)行通信,利用Express web框架發(fā)送請(qǐng)求和相應(yīng)請(qǐng)求。最后,我們使用ngrok將這個(gè)Express web Server暴露到外網(wǎng),這樣我們就可以通過(guò)短信讓Twilio通信給你的微控制器。
現(xiàn)在,我們可以開(kāi)始動(dòng)手了,將我的微控制器跟門鎖鏈接上。
步驟2:裝配
我們將使用一個(gè)伺服電機(jī)控制門鎖。它就是一個(gè)馬達(dá),動(dòng)力軸需要能旋轉(zhuǎn)180度的那種,這樣我們才能讓門鎖轉(zhuǎn)開(kāi)和閉合。
這個(gè)伺服馬達(dá)有三根線—火線(紅),零線(黑),控制線(通常是黃色或白色)。微處理器上有很多口,將馬達(dá)的火線連接5v電力口,零線接入GND地線口,控制線接入Digital Pin 12口,如下圖:
就這樣,我的馬達(dá)和微控制器連接到了一起,我們?cè)賹⑺烷T鎖裝配到一起。
我喜歡用家里常用的東西來(lái)開(kāi)發(fā)這些設(shè)備,但如果你能連接上一個(gè)3D打印機(jī),你可以設(shè)計(jì)和打印出自己的鎖扣裝置。
因?yàn)槭鞘痉?,我使用了紙板和膠帶來(lái)將電機(jī)和門鎖固定到一起。
將兩個(gè)金屬棍(或其它堅(jiān)固的細(xì)棍)幫到馬達(dá)上,用東西墊一下:
使用紙板(或其它比較硬的東西)當(dāng)做門鎖和電機(jī)之間的連接填充物:
用膠帶將電機(jī)和門鎖綁到一起,確保是綁在正確的一面,讓電機(jī)轉(zhuǎn)動(dòng)的方向是開(kāi)鎖或關(guān)鎖的方向:
最后,我們將電動(dòng)機(jī)軸固定到鎖鈕上:
現(xiàn)在我們已經(jīng)將電機(jī)和門鎖死死的固定到一起了:
步驟3:編寫控制程序
電機(jī)和微控制器已經(jīng)連接,Node.js和Arduino等軟件也已經(jīng)安裝了,現(xiàn)在我們需要運(yùn)行下面的命令來(lái)安裝必要的node.js模塊。注意,如果你使用的是Windows,你需要按照node-serialport Windows安裝指令。
- npm install serialport twilio express
Node-Serialport能夠讓你輕松的通過(guò)Arduino微控制器串口跟Node.js程序交互。我們將要使用它從Twilio里接受短信請(qǐng)求,并傳遞指令給Arduino微控制器讓它關(guān)鎖或開(kāi)鎖。
Express是一個(gè)簡(jiǎn)單的node.js web框架。而twilio模塊能讓我們輕松的和Twilio API交互。
首先,我們打開(kāi)Arduino IDE,建立一個(gè)新的Arduino開(kāi)發(fā)框架。第一步我們需要打開(kāi)一個(gè)9600波特的串口連接,跟伺服馬達(dá)接通(12口)。
- #include
- Servo myservo;
- int servoPin = 12;
- int lock = 0;
- int unlock = 180;
- void setup() {
- // initialize serial:
- Serial.begin(9600);
- myservo.attach(servoPin);
- myservo.write(lock);
- }
我們告訴微處理器,伺服馬達(dá)的0位置是“鎖住”,180位置是“解鎖”。跟據(jù)你是如何將馬達(dá)跟門鎖捆綁的,也許需要交換調(diào)整這個(gè)位置。當(dāng)微控制器啟動(dòng)時(shí),它會(huì)告訴馬達(dá)移動(dòng)到“鎖住”位置。
接下來(lái),我們將從串口連接上讀取一個(gè)字符,來(lái)判定是否應(yīng)該調(diào)動(dòng)馬達(dá)運(yùn)行。
- void loop() {
- // Recieve data from Node and write it to a String
- while (Serial.available()) {
- char inChar = (char)Serial.read();
- if(inChar == 'V'){ // end character for locking
- if (myservo.read() >= 90) {
- Serial.println("L");
- myservo.write(lock);
- delay(3000);
- }
- else {
- Serial.println("U");
- myservo.write(unlock);
- delay(3000);
- }
- }
- }
- }
Arduino用來(lái)分析的串口輸入是來(lái)自node.js腳本的輸出,下面我們會(huì)介紹這個(gè)腳本。
在Arduino IDE開(kāi)發(fā)環(huán)境外,我們用一個(gè)文本編輯器創(chuàng)建一個(gè)新文件,叫做nodelock.js,文件的開(kāi)頭是導(dǎo)入前面我們用npm安裝的模塊:
- var twilio = require('twilio'),
- SerialPort = require("serialport").SerialPort,
- express = require('express');
下面我們將建立新express web server和serialPort連接:
- var app = express();
- var serialPort = new SerialPort("/dev/tty.usbmodem1411", {
- baudrate: 9600
- });
注意,我們指定了要連接的USB端口和波特率。你可能需要根據(jù)你的計(jì)算機(jī)的情況修改這個(gè)USB端口。你可以在Arduino->Tools->Port菜單上找到你的可用的USB端口號(hào)。
下面我們要設(shè)定HTTP相關(guān)信息,調(diào)用/sms:
- app.use(express.bodyParser());
- app.post('/sms', twilio.webhook('your auth token', { host:'foo.herokuapp.com', protocol:'https' }), function(req, res){
- });
我們需要告訴express服務(wù)器通過(guò)/sms地址接受POST請(qǐng)求,使用bodyParser分析請(qǐng)求內(nèi)容,獲取來(lái)自Twilio的短信信息。我們使用twilio的webhook方法來(lái)驗(yàn)證請(qǐng)求來(lái)源的可靠性。
現(xiàn)在,我們有了接收短信的地址,在試一下之前,我們應(yīng)該檢查一下發(fā)短信的號(hào)碼是否是我們用來(lái)控制鎖的號(hào)碼。
- app.post('/sms', twilio.webhook('your auth token', { host:'foo.herokuapp.com', protocol:'https' }), function(req, res){
- if (req.body.From == "+12128675309") {
- console.log("verified number!");
- } else {
- console.log("Wrong number!");
- sendMessage(res, "Invalid number!");
- }
- });
在驗(yàn)證號(hào)碼的代碼段里,我們可以加入一個(gè)處理發(fā)送和相應(yīng)Arduino微控制器上串口連接的功能。
- serialPort.once('data', function(data) {
- if (data.toString().indexOf('U') > -1) { //check if the Arduino returned a U for unlocking
- sendMessage(res, 'Unlocking!');
- }
- else if (data.toString().indexOf('L') > -1) {
- sendMessage(res, 'Locking!');
- }
- else {
- sendMessage(res, 'ERROR');
- }
- console.log('data received: ' + data);
- });
- serialPort.write("V", function(err, results) {
- if (err) {
- console.log('err ' + err);
- }
- console.log('results ' + results);
- });
這代碼看起來(lái)很雜亂,但這是相當(dāng)直接的寫法。我們?cè)O(shè)定了事件處理器從微控制器里接受數(shù)據(jù)。這個(gè)事件處理器會(huì)檢查Arduino微控制器發(fā)送的是 “U” 還是 “L” ,我們獲取這個(gè)值,并用sendMessage函數(shù)將信息反饋給用戶。
設(shè)定了事件處理器后,我們向Arduino微控制器里寫入“V”字符,告訴它接收到了短信,它現(xiàn)在應(yīng)該打開(kāi)/關(guān)閉門鎖。
我們現(xiàn)在往文件中加入sendMessage函數(shù),它有2個(gè)參數(shù):res和message。
- function sendMessage(res, message) {
- var resp = new twilio.TwimlResponse();
- resp.message(message);
- res.type('text/xml');
- res.send(resp.toString());
- }
調(diào)用sendMessage函數(shù)會(huì)給用戶發(fā)送TwiML響應(yīng)信息。TwiML是XML的子集,Twilio用它來(lái)傳遞短消息指令。在我們這里,我們用它告訴Twilio響應(yīng)我發(fā)送的SMS信息。用戶也許會(huì)發(fā)送“unlock”,程序會(huì)通過(guò)Twilio SMS回復(fù) “Unlocking!”
我們已經(jīng)配置了SMS處理器,最后只需要打開(kāi)SerialPort,啟動(dòng)Express web server,我們的應(yīng)用就開(kāi)發(fā)完了:
- serialPort.open( function () {
- app.listen(3000);
- console.log('Listening on port 3000');
- });
這就是所有我們需要的代碼?,F(xiàn)在,如果你上傳我們之前寫的Arduino代碼,運(yùn)行nodelock.js,方法是在終端里執(zhí)行node nodelock.js,程序就啟動(dòng)了。
如果你在開(kāi)發(fā)的過(guò)程中遇到了錯(cuò)誤,可跟這些代碼對(duì)比一下看是什么問(wèn)題。
在創(chuàng)建并登陸你的Twilio帳號(hào)后,到 Twilio控制臺(tái),點(diǎn)擊號(hào)碼標(biāo)簽,選擇你希望用來(lái)控制鎖的號(hào)碼。你會(huì)看到兩個(gè)框,語(yǔ)音請(qǐng)求地址(Voice Request URL)和消息請(qǐng)求地址(Messaging Request URL)。我們使用Messaging Request URL來(lái)傳遞我們的短信文本信息。
因?yàn)門wilio是通過(guò)HTTP請(qǐng)求通信的,我們需要有一個(gè)能從公網(wǎng)上訪問(wèn)的地址,當(dāng)有消息到達(dá)時(shí),Twilio會(huì)將信息傳遞跟這個(gè)地址。于是我們之前安裝的ngrok就起作用了。
等你的node.js服務(wù)器起來(lái),開(kāi)一個(gè)終端窗口,在你安裝ngrok的目錄下輸入./ngrok 3000,這里你需要指定一個(gè)地址,通過(guò)它,外部服務(wù)能訪問(wèn)你的本地服務(wù)器。在這個(gè)地址后面跟上/sms,填入Twilio Messaging Request URL欄里,保存設(shè)置,試著發(fā)送一個(gè)短信!你的門鎖應(yīng)該隨著短信自動(dòng)打開(kāi)或關(guān)閉。
祝大家玩的愉快,編程開(kāi)心!
[英文原文:Build Your Own Lockitron With Twilio, Arduino, and Node.js ]