使用 JavaScript 進行硬件黑客攻擊

已發表: 2022-03-10
快速總結 ↬物聯網(IoT) 使互聯網能夠超越瀏覽器。 這些“東西”由電子網絡設備組成,能夠通過傳感器與物理世界交互,傳感器將捕獲的數據反饋回生態系統。 目前,這些設備大多是產品,設計時考慮到特定目的,一個典型的例子是追踪活動的健身手環。 它將收集到的信息報告給應用程序,然後應用程序能夠分析數據並提供建議和動力以進一步推動用戶。

物聯網(IoT) 使互聯網能夠超越瀏覽器。 這些“東西”由電子網絡設備組成,能夠通過傳感器與物理世界交互,傳感器將捕獲的數據反饋回生態系統。

目前,這些設備大多是產品,設計時考慮到特定目的,一個典型的例子是追踪活動的健身手環。 它將收集到的信息報告給應用程序,然後應用程序能夠分析數據並提供建議和動力以進一步推動用戶。

關於 SmashingMag 的進一步閱讀

  • 選擇正確的原型設計工具
  • 如何原型物聯網體驗:構建硬件
  • 原型物聯網體驗:配置軟件
  • 使用 TAP 和 Adob​​e Fireworks 進行 iOS 原型設計

在構建物聯網設備時,任務通常分為兩個角色:硬件工程師創建物理設備,開發人員創建生態系統。 然而,這並不總是必要的。 就 JavaScript 而言,它的同構特性允許一種語言在多個平台(包括硬件)上使用。

跳躍後更多! 繼續往下看↓

這是喬治,會說話的植物,物聯網的一個(相當暴躁的)補充。 他的傳感器收集周圍環境的數據,包括土壤的水分含量、環境溫度和光照強度。 憑藉他的 8 × 8 LED 臉,他能夠將他的不滿形象化,並使用 HTML5 的 Web Speech API 諷刺地回答您的平凡問題。 George 是一個很好的例子,說明瞭如何使用與硬件相結合的 Web 技術來提供新的和引人入勝的體驗。

本文介紹瞭如何開始使用 JavaScript 為您自己的 IoT 設備構建的基礎知識。

入門

傳統上,只有電氣工程師才會嘗試構建硬件原型和聯網設備。 隨著 Arduino UNO、Particle(以前的 Spark Core)和 Raspberry Pi 等開發板的出現,這種情況發生了變化。

開發板模仿計算機上的主板。 它們具有輸入和輸出插座,例如 USB 和電源,以及允許您添加外部組件的插針板。 微控制器芯片充當處理器,運行應用程序代碼並與輸入和輸出通信。 該芯片相對較慢,專門設計用於執行簡單的任務,例如讀取傳感器數據。 但是,它還具有切換能力,可以改變燈、電機和更多組件的電源。

Prototype development boards
一小部分開發板,有各種不同的形狀和尺寸。 (查看大圖)

創客運動在過去幾年中越來越受歡迎,構建物聯網設備已成為一項大生意。 這擴大了開發板的市場,現在提供的範圍很廣,每個都有自己的特點。 競爭導致許多人專注於獨特的賣點,例如無線通信(使用 Wi-Fi 和藍牙芯片)、尺寸和電池壽命。 在構建您自己的設備時,您需要考慮您需要哪些物理屬性。 同樣,軟件也會影響決策,例如您可以在板上運行的編程語言。 徹底研究並選擇最適合您需求的電路板。

在此處的示例中,我們使用的是 Arduino UNO。 這種特殊的開發板可能是市場上最受歡迎的,因為它非常易於使用。 如果您剛剛開始,我們建議您購買入門套件,類似於 Arduino 提供的東西。 它將為您選擇的開發板提供兼容的組件,並且通常會提供大量文檔來幫助您入門。

電力和電路的基礎知識

顧名思義,電子電路是圓形的。 電子從電路周圍的電源(例如電池)的正極流向同一電源的負極。

了解電路內部發生的物理現象的最簡單方法是將其與水箱系統進行比較。 管道中的水就像電線中的電子一樣流動。 這些電子形成了為電路組件供電的電流。

Water tank system.
水箱系統具有與電路相同的特性。 (查看大圖)

正如儲存在水箱中的水量會影響水龍頭上的壓力一樣,電源中的電子越多,它的充電量就越多。 這是電壓。 電壓越高,負極和正極之間存在的電壓就越大,從而控制電路周圍電子的速度。

就像一定體積的水流過管道一樣,電路的電流是指流過導線的電子數量。 這在構建電路時很重要,因為您需要確保每個組件都接收到足夠的數據來執行其任務。 電流以安培或安培 (A) 為單位測量,可以為我們提供有關使用的電子數量的信息。 例如,如果電機消耗 100 毫安 (mA),而電池的容量為 1000 毫安/小時 (mAh),那麼我們一次充電可以使電機運行 10 小時。

LED alight.
當電子流過 LED 時,它們會點亮它。 (查看大圖)

當電路中的組件運行所需的電流比電路中的電流少時,它們可能會接收到過多的功率併中斷。 在這種情況下,需要引入阻力以防止這種情況發生。 使用我們的水類比,管道的直徑將限制可以流過它的水量,就像電阻限制電子的流動一樣。

電阻器是用來降低電流的元件。 它們所施加的電阻大小不同,如電阻器外部的彩色條帶所示。 不同的顏色代表不同的數字,將這些帶加在一起將顯示該特定電阻器的電阻。 (可以使用計算器!)值越高,施加在電路上的電阻就越大,對組件造成損壞的可能性就越小。 使用歐姆定律——電阻等於電壓除以電流(或R = V / I )——您可以計算出電路中所需的精確電阻。

你好世界

在涵蓋了基礎知識之後,我們可以看一個簡單的示例來可視化它們是如何組合在一起的。 我們將進行硬件開發的“Hello World”:讓 LED 閃爍。

如前所述,您可以使用多個開發板中的任何一個。 在本例中,我們將使用 Arduino UNO。 我們還將使用運行 Mac OS X 的 Mac,但所有示例也應該在 Windows 上運行。

硬件

你會需要:

  • 1 × Arduino UNO
  • 1 × 無焊麵包板
  • 1×標準LED
  • 1×220歐姆電阻
  • 2 × 跨接電纜
Hello World components
構建此項目所需的所有組件。 (查看大圖)

這包括一些尚未提及的組件:

  • 跨接電纜用於引導電子流,就像電路中使用任何電線一樣。
  • LED是發光二極管的簡稱,本質上是一個小燈泡。 它有一條長腿和一條短腿。 較長的腿表示電路的正流應該進入的位置,較短的腿表示負輸出。 如果您弄錯了這些方法,LED 將不會亮起。
  • 無焊麵包板(帶孔的白色塊)是一種原型製作工具,無需焊接即可創建電路,從而可以輕鬆更改和糾正電路,以及重複使用組件。 它們有許多不同的形狀和大小,但都扮演著相同的角色。

下圖顯示了電流的流動。 組件可用於將部分鏈接在一起,如下例中的 LED 和電阻器所做的那樣。 在較大的麵包板上,​​外部垂直線通常用於連接正負跨接電纜,以分隔您正在設計的電路。

Solderless breadboard
顯示電流流動的無焊麵包板。 (查看大圖)

插入您的組件,如下圖所示 - 匹配引腳。 在繼續下一節時,這將使事情變得更容易。

Blinking LED schematic
“Hello World”練習的示意圖。 (查看大圖)

要啟動電路,請從 Arduino 上的引腳 10 連接一根跳線。 這是 Arduino 開始與電路對話的地方。 您可以使用 Arduino 右側的任何編號的針腳——只要確保您的代碼引用正確的針腳即可。

為確保理想量的電流流過 LED,需要使用電阻器。 與 LED 不同,它以哪種方式插入電路並不重要。

引腳 10 是否允許電流通過(由您的代碼控制)將決定 LED 是打開還是關閉。

另一根跳線然後連接到 LED 的負極並返回到地以完成電路。 簡單的!

完成後,您的電路應如下圖所示。 通過 USB 將其插入計算機。 下一個任務是設置 Arduino 以使用 JavaScript。

Hello World circuit in real life
這就是您的電路在構建時的外觀。 (查看大圖)

在編寫任何軟件之前,我們需要確保 Arduino 具有正確的固件,以便它可以與 JavaScript 一起使用。 固件本質上為計算機公開了一個 API,以便代碼可以通過 USB 端口與電路板交互。

從 Arduino 網站下載並安裝集成開發環境 (IDE)。 接下來打開 IDE,確保您的 Arduino 已通過 USB 插入。

在運行任何東西之前,您還需要檢查您是否擁有正確的 USB 端口。 轉到“工具”→“端口”。 名稱可以不同,因此一個好的規則是選擇一個端口,在 Mac OS X 上選擇名稱中包含“tty”和“usb”,在 Windows 上選擇名稱中包含“COM”的端口。

完成後,您現在可以上傳固件。 選擇“文件”→“示例”→“Firmata”→“標準 Firmata”。 完成後,選擇“文件”→“在 Mac 上上傳”(或“草圖”→“在 Windows 上上傳”)。

Arduino IDE screenshot
找到合適的固件可能很棘手; 這是你會找到它的地方。 (查看大圖)

現在是時候編寫一些 JavaScript 了!

軟件

要使用 JavaScript 控制 LED,我們需要使用為 Node.js 構建的名為 Johnny-Five 的庫。 基本上,它是由 Bocoup 團隊構建的一個庫,旨在讓網絡社區更容易訪問構建硬件。 如果您不知道 Node.js 是什麼或如何使用它,Elliot Bonneville 在這個網站上有很好的介紹。

因為我們示例的核心使用了 Arduino,所以這個庫允許我們的機器通過 USB 端口連接到硬件。

要開始使用,您需要安裝 Node.js。 如果不是,您可以從 Node.js 網站下載它。 這還將安裝 Node Package Manager (npm),我們將使用它來安裝應用程序的所有依賴項。 該示例在 Mac 上運行,使用終端作為命令行工具; 但是,因為 Node.js 是多平台的,所以它可以在任何機器上運行。

本文中的所有代碼都可以在 GitHub 上找到。

要安裝此項目所需的所有依賴項,您需要創建一個package.json文件,該文件可以從下面的代碼中獲取。 這是運行示例所需的庫的購物清單。 初始化install命令後,npm 將出去並獲取所有運行所需的所有組件。 此文件必須在您的根文件夾中。

 { "name": "Hardware-Hacking-with-JavaScript", "description": "Smashing Magazine - Hardware Hacking with JavaScript", "version": "0.0.1", "homepage": "https://www.james-miller.co.uk/", "keywords": ["arduino","tutorial","hardware"], "author": { "name":"James Miller & Mate Marschalko" }, "repository": { "type": "git", "url": "git://github.com/jimhunty/Hardware-Hacking-with-JavaScript.git" }, "bugs": "https://github.com/jimhunty/Hardware-Hacking-with-JavaScript/issues", "license": "MIT", "dependencies": { "johnny-five": "^0.9.13" } }

在您的命令行工具中,確保您與package.json文件位於為此示例創建的同一文件夾中; 然後,運行npm install 。 如果您沒有安裝這些軟件包的權限,請改用sudo npm install

現在,您需要創建應用程序代碼來運行我們的示例。 我們將此文件命名為blink-led.js 。 評論詳細說明了正在發生的事情。

 // Johnny-Five is our JavaScript framework for accessing Arduino. var jfive = require("johnny-five"); var board, led; board = new jfive.Board(); // Similar to jQuery, we wait for the board to be ready. board.on("ready", function() { // 10 represents the pin number that the LED is plugged into. led = new jfive.Led(10) // The LED blinks (ie turns on and off) every 1000 milliseconds. led.blink(1000); });

首先,加載庫,然後初始化變量。 使用構造函數創建一個新的Board實例, on ready函數將使板預熱並準備好接收指令。 因為您將連接到 LED 的跨接電纜插入引腳 10,所以需要在led變量中定義它。 然後使用blink方法在 1 秒的階段打開和關閉燈。

現在,您已經擁有了開始這場燈光秀所需的一切——調高音樂! 確保您的 Arduino 已插入並且電路已全部設置好。 在命令行中,運行node blink-led.js ,將文件名替換為您調用的代碼。 你現在應該有一個閃爍的燈。

嘗試修改代碼以使燈閃爍更快或更慢。 每次執行此操作時,您都需要在終端中重新啟動代碼。 你不妨試試led.pulse() ; 這將使 LED 淡入淡出,而不是僅在沒有過渡的情況下切換。

家庭監控

你已經學到了很多東西! 現在您可以將這些知識用於使用並構建一個簡單的家庭監控系統,類似於 Nest 和 Hive 等商業產品。

這一次,您將使用溫度傳感器,從 Node.js 服務器連接到 Arduino。 傳感器將讀取溫度並將其輸入瀏覽器,該瀏覽器將在一個簡單的網頁上顯示數據。

How the interface will look
頁面的背景顏色反映了溫度。 (查看大圖)

硬件

你會需要:

  • 1 × Arduino UNO
  • 1 × 無焊麵包板
  • 1 × TMP36 溫度傳感器
  • 3 × 跨接電纜

為本示例選擇的溫度傳感器可用於大多數入門套件,並且單獨購買非常便宜。

Home-monitoring project components
構建家庭監控項目所需的組件。 (查看大圖)

在前面的 LED 閃爍示例中,您設置了計算機上運行的 Node.js 服務器和 Arduino 之間的連接。 此連接還可用於從連接到 Arduino 的傳感器讀取數據。

Home-monitoring circuit schematic
家庭監控電路示意圖。 (查看大圖)

以上是完成的電路。 嘗試將此引腳與引腳匹配。

處理溫度傳感器時要小心,因為很容易把腿弄混。 組件的平面是前面,在連接傳感器時應該面向您。 由於三條腿中的每一條都有不同的用途,因此錯誤地接線將意味著您的電路將無法工作。

模擬輸入引腳是沿板左側排列的五個引腳。 Arduino 既有模擬引腳又有數字引腳,既有輸入又有輸出。 數字意味著只有兩種狀態——開和關(或電信號和無電信號)——非常適合僅解釋兩種狀態的按鈕和其他二進制開關。 另一方面,模擬輸入可以表示一系列值,Arduino 上的模擬輸入引腳可以測量 0 到 5 伏之間的任何電壓(並產生該讀數的 10 位值)。 傳感器的溫度讀數將以與空氣溫度成比例的可變電阻測量值返回。

將傳感器中間的信號引腳連接到模擬輸入 A0。 將左側引腳連接到 5V 引腳(正極),將右側引腳接地(負極)以完成電路。

Home-monitoring circuit in real life
完成的家庭監控電路。 (查看大圖)

您的電路現在應該類似於上圖。 接下來,您需要創建一個新文件來讀取溫度傳感器。 該文件將以與上一個示例相同的方式啟動,加載 Johnny-Five 庫,初始化一個新的板實例,然後添加一個on ready事件偵聽器。

 var jfive = require("johnny-five"); board = new jfive.Board(); board.on("ready", function() { // We create a new sensor instance and define the sensor type and the pin it's connected to. var tempSensor = new jfive.Thermometer({ controller: "TMP36", pin: "A0" }); // We add an event listener to the sensor and handle the incoming data. tempSensor.on("data", function() { // The data object also has a fahrenheit property, if that's what we are after. console.log(this.celsius + "°C"); }); });

將這段代碼保存為temperature.js ,並通過輸入node temperature.js從控制台運行它。

因為代碼中使用了console.log ,所以讀數會輸出到終端進行調試。

Terminal showing temperature data
溫度數據應該開始很快打印出來。 (查看大圖)

服務器和套接字

現在你有一個在 Node.js 中運行的工作溫度計。 如果您考慮可用於處理和使用這些數據的所有不同 Node.js 模塊,僅這個簡單的示例就開啟了一系列可能性。 您可以將其保存到 Google 電子表格、發推文或撰寫有關它的信息,甚至可以使用 WebSockets 將這些數據實時流式傳輸到瀏覽器——這就是您接下來要做的!

Flow diagram showing data movement
來自每個設備的數據流。 (查看大圖)

要建立與瀏覽器的連接並傳輸傳感器數據,我們需要啟動一個 Node.js HTTP 服務器來提供我們的 HTML 文檔,然後打開它們之間的 WebSocket 連接。 使用 Express 庫在 Node.js 中啟動 Web 服務器相對簡單。 首先,從終端安裝它:

 npm install --save express

安裝後,這些代碼行將實例化服務器:

 // Load libraries and then initialize the server. var app = require('express')(); var http = require('http').Server(app); // When the user requests the root of the page (/), we respond with index.html. app.get('/', function(req, res){ res.sendFile(__dirname + '/index.html'); }); // We listen for connections on port 3000. http.listen(3000, function(){ console.log('listening on *:3000'); });

將此保存為server.js文件。

在此服務器代碼中,前兩行加載所需的庫並創建一個 HTTP 服務器實例。 接下來,當用戶請求根目錄 ( / ) 時,簡單的路由邏輯會為項目文件夾中的index.html文件提供服務。 最後,端口3000監聽連接。

要對此進行測試,請在項目文件夾的根目錄中創建一個標準index.html文件。 在命令行中,導航到項目的文件夾並輸入node server.js 。 如果您隨後在瀏覽器中鍵入https://localhost:3000或您機器的 IP 地址和端口(例如https://190.140.0.00:3000 ),您應該會看到標準index.html頁面。 這意味著您的服務器已全部設置完畢。

這絕對比配置 Apache 服務器容易!

在將這段代碼與temperature.js文件合併之前,我們將設置 WebSocket 連接。

WebSocket 使打開瀏覽器和服務器之間的通信會話成為可能。 使用此 API,您可以發送雙向實時消息並接收事件驅動的響應,而無需輪詢回复。 Socket.IO 是您將用來建立和處理此連接的 Node.js 模塊。 像安裝 Express 和 Johnny-5 一樣安裝 Socket.IO:

 npm install --save socket.io

請注意您的package.json文件現在如何在依賴項下使用 Express 和 Socket.IO 進行更新? 這意味著任何希望在他們的機器上運行您的應用程序的人都可以簡單地運行npm install ,並且您加載的所有模塊依賴項都將立即安裝。 好的! 現在您可以將 WebSocket 功能添加到工作的server.js代碼中。 下面是完整的例子:

 var app = require('express')(); var http = require('http').Server(app); // Load the Socket.IO library. var io = require('socket.io')(http); app.get('/', function(req, res){ res.sendfile('index.html'); }); // Establish the WebSocket connection with the browser. io.on('connection', function(socket){ console.log('a user connected'); }); http.listen(3000, function(){ console.log('listening on *:3000'); });

首先,加載 Socket.IO,然後創建一個on connection事件監聽器。 這將在用戶加載index.html文件時觸發。

index.html頁面上,需要初始化 Socket.IO 客戶端庫以便與服務器通信。 要為此準備 HTML 文件,請在結束body標記之前添加以下代碼:

 <script src="https://cdn.socket.io/socket.io-1.2.0.js"></script> <script> var socket = io(); </script>

現在應該已經建立了連接,在通過 localhost 鏈接加載索引頁面時,您應該會在命令行中看到“A user has connected”消息。

現在,您可以使用socket.emit()函數從服務器向瀏覽器發送消息。 您可以通過替換server.js中的先前函數來做到這一點:

 io.on('connection', function(socket){ console.log('a user connected'); socket.emit('Server message', “Hello from the server!”); });

這是您需要修改index.html以接收消息的方式:

 <script src="https://cdn.socket.io/socket.io-1.2.0.js"></script> <script> var socket = io(); socket.on('Server message', function (message) { console.log(message); }); </script>

如果您已正確完成所有操作,您應該會看到“來自服務器的您好!” 瀏覽器控制台中的消息。 恭喜! 這意味著您已經在 Node.js HTTP 服務器和瀏覽器之間建立了實時 WebSocket 連接!

這真的非常有用,而且不僅僅適用於這個項目。 WebSocket 連接可用於在多個瀏覽器之間進行通信,以創建聊天應用程序、多人遊戲等等!

WebSockets enabled screenshot
啟用 WebSockets! 您現在已連接。 (查看大圖)

現在是時候將處理與 Arduino 通信的temperature.js文件與負責連接到瀏覽器的新 WebSocket 服務器代碼合併了。

這需要擴展server.js

 var app = require('express')(); var http = require('http').Server(app); var io = require('socket.io')(http); var jfive = require("johnny-five"); var board = new jfive.Board(); var board, socket, connected = false; app.get('/', function(req, res){ res.sendFile(__dirname + '/index.html'); }); io.on('connection', function(s){ console.log('A user has connected'); // Tracking connection connected = true; // Saving this for the board on ready callback function socket = s; }); board.on("ready", function() { console.log('board has connected'); var tempSensor = new jfive.Thermometer({ controller: "TMP36", pin: "A0" }); tempSensor.on("data", function() { // We send the temperature when the browser is connected. if(connected) socket.emit('Temperature reading', this.celsius); }); }); http.listen(3000, function(){ console.log('listening on *:3000'); });

在這裡,您只是從temperature.js複製了加載 Johnny-Five 並初始化電路板的行,以及整個board on ready功能。

您還添加了兩個新變量:一個用於跟踪 WebSocket 連接,另一個用於存儲套接字實例以供其他函數訪問——在本例中,用於使用它來發送和接收消息的board on ready函數。

現在,需要更新index.html文件以處理來自套接字連接的數據Temperature reading 。 下面的代碼需要添加到之前存在Server message處理程序的腳本元素中的 HTML 文檔中。

 socket.on('Temperature reading', function (message) { console.log(message); });

界面

最後要做的就是在index.html中添加幾行 HTML 和 CSS,以便以用戶友好的方式顯示溫度讀數。 您還將根據溫度更新背景顏色,使其在藍色(冷)和橙色(熱)之間變化。 HTML 非常簡單:只有一個h1元素來保存數字。

以下內容需要添加到body中。

 <h1 class="temperature">0C</h1>

大而細的字體應該與數字配合得很好; 試試 Lato,一種來自 Google 字體庫的免費字體。 將其加載到文檔的head

 <link href='https://fonts.googleapis.com/css?family=Lato:100' rel='stylesheet' type='text/css'>

在這個例子中,樣式是最小的。 唯一棘手的一點是temperature標籤的加載方式。 它使用content CSS 屬性獲取類名並將其添加到:before偽元素中。

 body { background-color: hsl(0, 60%, 65%); transition: background-color 1s; } h1 { font-family: 'Lato', sans-serif; font-size: 120px; font-weight: 100; color: white; text-align: center; margin: 60px; } h1:before{ content: attr(class) ":"; font-size: 22px; position: relative; top: -69px; left: 0; text-transform: uppercase; }
Browser showing temperature data
您現在正在將溫度數據實時發送到您的界面。 項目完成! (查看大圖)

這看起來已經很漂亮了!

最後,添加幾行 JavaScript 以在接收到 WebSocket 消息時更新值,並更改背景顏色。

 <script src="https://cdn.socket.io/socket.io-1.2.0.js"></script> <script> var socket = io(), temperature = document.querySelector(".temperature"); socket.on('Temperature reading', function(message) { // Rounding down the decimal values and adding C temperature.innerHTML = parseInt(message) + "C"; // Calculating the hue for the background color and changing it var hue = 200 - (parseInt(message) * 5); document.body.style.backgroundColor = "hsl(" + hue + ", 60%, 65%)"; }); </script>

你完成了! Arduino 溫度讀數現在將在瀏覽器中實時顯示。

結論

雖然構建自己的硬件的前景可能令人生畏,但希望在完成這兩個示例之後,您已經在考慮可能性併計劃下一個項目。 許多組件與 Johnny-Five 庫兼容,這意味著唯一的限制是您的想像力。

資源

  • “使用 JavaScript 進行硬件黑客攻擊”,James Miller 和 Mate Marshalko,GitHub
    該項目所需的所有代碼
  • 約翰尼五號,里克沃爾德倫,GitHub
    “JavaScript 機器人編程框架”
  • 設備上的網絡,Mate Marshalko
    一個使用 JavaScript 和其他網絡技術進行電子黑客攻擊的網站
  • 製作
    Maker Media 的在線雜誌,針對創客,提供新項目和技巧
  • Node.js 的 Arduino 實驗者指南
    Johnny-Five 的更多 JavaScript 和 Arduino 項目