不久前在 Youtube 上看到一則影片,主角只出一張嘴,就能透過 Siri 讓家裡的電器用品乖乖聽話,就像小時候的科幻片描述未來的居家生活,頗為神奇。只不過影片中並沒有說明實作的方法,只在影片下方留言中提到幾個關鍵字,引起了我的好奇。
從 iOS 開發者的角度來看,原以為是 iOS 10 的 Sirikit 的新功能,於是我嘗試呼叫 Siri ,得到的是以下的結果:
Siri 回答提到「打理這個家」,大概能猜得到,iOS 使用 Homekit 控制家電 ,而 Siri 與 Homekit 整合已經是 iOS 10 內建的功能,所以 Siri 控制家電並非使用 Sirikit ,而是用 Homekit 來實現。換言之,所謂家電用品支援 Homekit 功能,就是除了能透過 iOS 10 內建的「家庭 App」來統一管理,並可自訂使用情境、場景與配件的設定,打造個人專屬的家電運作模式之外,還能透過 iOS 的 Siri 語音助理,「用講的」操控家電的部分功能。「家庭 App 管理家電」與「Siri 語音控制家電」兩項重點功能,就是 iOS 10 的 Homekit 智慧家電平台。
近年來有越來越多新的家電產品標榜「智慧家電」功能,但台灣民眾對這一塊的熱度不夠,目前市面上還不普及,現役家電產品也大多還能用個很多年,除非在裝修新房時就納入智慧家電的規劃,否則只有極少數的人為了享受「智慧家電生活」把家裏的電器產品全部換掉(據說有個社會名人就這樣搞,打造智慧家庭就花了四千萬台幣)。於是換個角度,有沒有辦法讓家裏面的現有家電,透過外掛手段來支援 Homekit 呢?答案是有的,價格也很低廉,只是要達到這樣的目標有一定的技術門檻,雖然不難,但也不算容易,因為不同的電器有不同的動作設定,納入 Homekit 之後更不一定支援家電原有的全部功能。
所以我可以理解為何一堆 Youtube 影片,尤其是中文的,大多沒有教學,畢竟有些實作步驟很有可能卡關,實作方式也會牽涉到特定的知識領域,寫了教學也不可能人人都能淺顯易懂。所以這篇文章並非新手教學,只會概略提出實作方式,除了幫自己做紀錄,也提供已有以下相關基礎知識,並且有興趣想嘗試的人做參考。
- 會使用 Arduino IDE 撰寫單晶片韌體。
- 略懂 Linux 終端機操作指令。
目標使用情境:以家裏運作多年的老冷氣機為例,利用 iOS 的 Homekit 功能來控制冷氣的基本功能「開」和「關」。
市售的傳統家用冷氣都有紅外線遙控器,但並不支援無線網路。所以要達到上述目標,實作目標分成兩大部分:
- 實作一組可支援網路操控的自製紅外線 WIFI 遙控器
- 在家裡的區域網路內,連接 Homekit 與自製的紅外線WIFI遙控器
一、支援 WIFI 網路操控的紅外線遙控器
這個部分教學就不少了,搜尋「Arduino+IRremote」就會跑出一堆。這裡再細分出兩階段:材料採購與軟體撰寫。
材料相當廉價,甚至於比你去夜市買一隻萬用遙控器還便宜。
- MCU/SoC 晶片:首先是必須支援聯網功能的單晶片,ESP8266 系列當然是不二人選,直接用 NodeMCU V1.0 就可以了,或是使用體積更小、更便宜的 WEMOS D1 mini 也行。這東西越來越便宜,台灣一個才一百多元,對岸的淘寶更便宜,合台幣不到 80 元,CP 值爆表,屌打一堆動輒千元的物聯網模組。
- 紅外線發射 LED :一顆才 2 元,台南市區的電子材料店約 10-15 元。因為發射時有方向性,可以併聯個2-3顆,每一顆朝不同的方向。
- 電晶體:NPN 型,例如 2N3904,作用是放大紅外線發射訊號,一顆也是 2-5 元。
元件接法可參考這個網頁,自製紅外線搖控器的硬體配置就這樣而已,材料費才台幣一百多元。至於運作的電源,找條 Micro-USB 線連接 NodeMCU 與帶電的 USB 埠就行了(電腦/充電器/行動電源…)。
NodeMCU V1.0 電路接法
WEMOS D1 mini 的電路接法,其實與 NodeMCU V1.0 相同,但體積更小。
再來是軟體撰寫的階段。倘若真的不會寫程式,那…請自行 Google 市面上已整合 WIFI + 紅外線 + 軟體 APP 的產品:Broadlink RM Pro(市價約 NT 980.-),以及如何把這產品掛上 Homekit 的教學,就可以按上一頁離開本文章了。
軟體撰寫使用 Arduino IDE + Arduino Code 開發撰寫,加掛以下三方套件,至於程式碼內容就不說明了,套件範例都有。
- IRremoteESP8266:ESP8266 驅動紅外線的套件。
- WiFiManager:ESP8266 超級好用的 Wifi 連線套件。
- <ESP8266mDNS.h>、<ESP8266WebServer.h>:ESP8266 Arduino Code 內建。讓 ESP8266 變成具備 DNS Name 的 WebServer,負責接收 HTTP Request 內容。
不過一開始我們不知道冷氣的紅外線指令的編碼內容,所以要買一顆紅外線接收器(我是買模組化的這個,理論上可以買更便宜的 LED 型),再用 IRremoteESP8266 提供的標準範例程式寫個 ESP8266 接收紅外線編碼的程式,學習原廠的搖控器就可取得紅外線的編碼內容,存成文字後就可以作為紅外線發射器的資料來源,可參考這篇文章的說明。
這個部分最終的目標為:在家裡的網路中隨便找一台電腦/平板/手機,打開瀏覽器,輸入網址就能驅動自製的紅外線發射器進行指定的動作,例如輸入 http://esp8266.local/airconditioner/on 就能讓自製遙控器發射「開冷氣」的紅外線編碼,http://esp8266.local/airconditioner/off 讓自製遙控器發射「關冷氣」的紅外線編碼。
當這個階段完成之後,只要把自製紅外線 WIFI 遙控器擺在冷氣(家電)可接收紅外線訊號的固定位置,就等於可以在家裡用電腦/平板/手機等裝置,用透過家裡的區域網路來控制家裡的冷氣開關,成功之後就可以寫個簡單的 App ,透過按按鈕或其他操作方式,來呼叫網址就行了。例如以下的幾個範例:
手機端的 Widget 工具:
macOS 電腦端的應用程式:
Windows PC 端的應用程式:
Web 版(將網頁程式上傳到 ESP8266 的 SPIFF 檔案空間)。
其實「用裝置遙控 ESP8266 聯網裝置」的動作不一定要透過 HTTP 協定,有太多方式了,例如使用 MQTT 協定搭配國外免費的 Broker 服務,預設就能直接跨越家裡區網的限制,不論人在世界的哪個地方,拿起手機或平板執行 MQTT 客戶端程式,就能控制家裏的 ESP8266 聯網裝置,但也意味別人也有機會駭入你家,所以使用網路 MQTT 服務要非常小心,這部分就不多提了。
二、連結 iOS Homekit 與自製紅外線WIFI遙控器
這邊就進入重點了。目前雖然有 ESP8266-Homekit 方案,但似乎並沒有 Arduino Code 的形式,所以要客製化周邊設備有不小的難度。現在看到大部分實作的方式是透過一個叫「homebridge」的服務作為橋接器,由這個橋接器負責周邊設備與 Homekit 的溝通,實作重點在軟體服務的安裝與設定。
(1) 安裝 homebridge 橋接器服務
知道上述動作原理之後,實作過程就是找台電腦建立「homebridge 」橋接器,並在橋接器上建立虛擬周邊與包含執行網址的設定(開/關冷氣的動作網址)。網路上大部分的教學是把 homebridge 安裝在「樹莓派(Raspberry Pi)」上,也有少部分教學是安裝在 Ubuntu,macOS,或 Windows 。每種作業系統安裝 homebridge 方式雖然不太相同,但也是大同小異。
由於我沒有樹莓派(雖然便宜,但一台也要一兩千元),所以我是採用建立 Ubuntu 14.04 (VirtualBox 虛擬機)的方式,來安裝啟動 homebridge 服務。VirtualBox 與 Ubuntu 作業系統也是免費下載,花費 0 元。與 Ubuntu 系出同門的 Debian 作業系統(正確說法為 Ubuntu 是 Debian 的一項分支),在安裝完 sudo 與 設定 sudoers 之後,也能使用以下相同的方式安裝 homebridge 服務。
Ubuntu 作業系統開啟終端機視窗,依序執行指令如下:
1. 執行 sudo apt-get update
如果出現以下的錯誤訊息:
E: 無法將 /var/lib/dpkg/lock 鎖定 - open (11: 資源暫時無法取得)
E: Unable to lock the administration directory (/var/lib/dpkg/), is another process using it?
可執行以下指令
sudo rm -rf /var/lib/dpkg/lock
2. 執行 sudo apt-get upgrade 等一段時間,這邊要等很久,14.04 虛擬機大概會跑10幾分鐘以上,甚至半個多小時。
如果一下子跑完,又說 xx 未被升級的話,可執行
apt-get dist-upgrade
3. 執行以下命令
sudo apt-get install -y samba screen git
sudo apt-get install curl
curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
sudo apt-get install -y nodejs
sudo npm install node-gyp
sudo apt-get install libavahi-compat-libdnssd-dev
4. 安裝 homebridge
執行 sudo npm install -g --unsafe-perm homebridge
不過 Ubuntu 14.04 很可能會遇到以下的錯誤訊息
nas@nas:~$ sudo npm install -g --unsafe-perm homebridge
/usr/bin/homebridge -> /usr/lib/node_modules/homebridge/bin/homebridge
> mdns@2.3.3 install /usr/lib/node_modules/homebridge/node_modules/mdns
> node-gyp rebuild
make: Entering directory `/usr/lib/node_modules/homebridge/node_modules/mdns/build'
CXX(target) Release/obj.target/dns_sd_bindings/src/dns_sd.o
make: g++: Command not found
make: *** [Release/obj.target/dns_sd_bindings/src/dns_sd.o] Error 127
make: Leaving directory `/usr/lib/node_modules/homebridge/node_modules/mdns/build'
gyp ERR! build error
gyp ERR! stack Error: `make` failed with exit code: 2
可執行以下五行指令修正問題
sudo rm -rf /usr/lib/node_modules/
sudo apt-get install build-essential
sudo apt-get install libkrb5-dev
sudo apt-get remove nodejs
sudo apt-get install nodejs
之後再執行一次 sudo npm install -g --unsafe-perm homebridge 試試看。
5. 測試 homebridge
輸入homebridge
回應
......
Scan this code with your HomeKit App on your iOS device to pair with Homebridge:
┌────────────┐
│ 031-45-154 │
└────────────┘
[2017-08-02 16:12:05] Homebridge is running on port 43761.
如果出現反白配對碼「 XXX-XX-XXX」的訊息,表示 homebridge 安裝完成。
這時候就可以打開 iOS 10 手機的「家庭 App」了,一路循指示開啟 iCloud 的「家庭」權限-->新增配件,就能看到有個叫「Homebridge」的裝置顯示在清單上。
不過這個時候先別急著設定,因為橋接器還沒有掛上虛擬周邊可供選取。先按「取消」離開,回到 Ubuntu 電腦進行操作。
(2) 安裝 homebridge 插件
homebridge 插件的目的,就是建立虛擬周邊設備掛進 homebridge 橋接器服務,並設定虛擬周邊的動作指令。有上百種插件任君挑選,每一種插件都有不同的週邊設備作用方式。要選哪個插件可以到這裡搜尋:
插件的功能可說是玲瑯滿目,坦白說要搞懂插件的運作與設定方式實在不容易,因為每一種的作用與目的都不同,甚至超出「周邊家電」的既定印象。例如這個「homebridge-openweathermap-temperature」插件,就是模擬一個溫度計周邊,用來顯示 OpenWeather 天氣服務網站的某指定城市現在氣溫。
先用這個插件為例,安裝的方式為:
A. 開啟終端機,執行命令 sudo npm install -g homebridge-openweathermap-temperature
B. 在 ~/.homebridge/ 建立(或修改)config.json,文字內容如下:
{ "bridge": { "name": "控制中心", "username": "AB:CD:EF:12:34:56", "port": 51826, "pin": "123-45-678" }, "description": "HomeBridge HTTP Status Control", "accessories": [ { "accessory": "OpenweathermapTemperature", "name": "台南市溫度", "url": "http://api.openweathermap.org/data/2.5/weather?q=Tainan&appid=[apikey需註冊OpenWeather帳號取得]" } ] }
C.終端機執行 homebridge 指令
看到 Load x accessories... 以及配對的 XXX-XX-XX 訊息時,就表示 homebridge 和配件都成功掛載啟動了。
若要讓 homebridge 於每次 Ubuntu 開機時自動執行,請參考這裡。
D. 回到 iOS 10 的「家庭 App」,依照畫面指示設定就行了。
最後就能在「家庭 App」看到一個配件,內容顯示 OpenWeather 查詢的城市溫度。
也可以呼叫 Siri 用講的給你聽。不過因為是「家庭周邊配件」,問 Siri 的時候要問「家裏溫度」才會顯示配件數字,若是只問「溫度」或「室外溫度」,它就會找 iOS 內建的天氣預報服務,而不是 Homekit 。
搞懂如何掛載插件的方法後,接著就可以選擇適合的插件,透過 HTTP 網址來執行冷氣的開關動作了。我找到符合有「開」與「關」對應動作網址的插件是「homebridge-http」
sudo npm install -g homebridge-http
接著編輯 config.json 內容,在「"accessories"」節點內插入以下內容:
{ "accessory": "Http", "name": "冷氣", "switchHandling": "realtime", "http_method": "GET", "on_url": "http://[開冷氣的網址]", "off_url": "http://[關冷氣的網址]", "status_on": "ON", "status_off": "OFF", "service": "Switch", "sendimmediately": "", "username": "", "password": "" }
重新執行 homebridge 之後,「家庭 App」就可以看到兩個配件按鈕。可以點擊冷氣配件按鈕進行開或關的動作。
不過這個插件遇到網路問題時會發生找不到 callback 函數的 BUG 而跳出,修正方式:
/usr/lib/node_modules/homebridge-http/index.js 從第 11 行加入 function callback(error){ if(error){ console.log('HTTP function failed: %s', error.message); } else{ console.log('HTTP function done with No Error...'); } }
插件可以一直加掛進 homebridge 橋接器內,例如再繼續加掛「homebridge-httptemperaturehumidity」就可以透過 HTTP 協定取得家裏的 ESP8266+DHT22 溫濕度數值,並透過 Siri 語音控制這些周邊。
sudo npm install -g homebridge-http-temperature-humidity
這個插件也有類似的問題,修正方式:
1. 修改 /usr/lib/node_modules/homebridge-http-temperature-humidity/index.js 在 var res = request(this.http_method, this.url,{}); 與 if(res.statusCode > 400){ 之間加入 var res = request(this.http_method, this.url,{}); if (typeof res === 'undefined'){ this.log('HTTP power function NOT succeeded : undefined'); this.temperature = -1; this.humidity = -1; callback(null, this.temperature); } else if(res.statusCode > 400){
2. 修改 /usr/lib/node_modules/homebridge-http-temperature-humidity/node_modules/sync-request/index.js ,目的是修正可能因網路問題造成 Javascript 程式錯誤或 JSON.parse 方法卡死的現象,修改內容重點在「標記 throw error 方法」與「增加 resErr 變數」的判斷,才不至於讓錯誤結果誤進 JSON 解析程序產生其他問題。
'use strict'; var fs = require('fs'); var spawnSync = require('child_process').spawnSync || require('spawn-sync'); var HttpResponse = require('http-response-object'); require('concat-stream'); require('then-request'); var JSON = require('./lib/json-buffer'); Function('', fs.readFileSync(require.resolve('./lib/worker.js'), 'utf8')); module.exports = doRequest; function doRequest(method, url, options) { var req = JSON.stringify({ method: method, url: url, options: options }); var res = spawnSync(process.execPath, [require.resolve('./lib/worker.js')], {input: req}); var resErr = 0; if (res.status !== 0) { console.log('doRequest res.stderr.toString: %s',res.stderr.toString()); resErr = 1; //throw new Error(res.stderr.toString()); } if (res.error) { if (typeof res.error === 'string') res.error = new Error(res.error); console.log('doRequest res.error === string '); resErr = 1; //throw res.error; } if (resErr === 0){ var response = JSON.parse(res.stdout); if (typeof response === 'undefined'){ console.log('httptemperaturehumidity: response JSON is undefined'); } else if (response.success) { return new HttpResponse(response.response.statusCode, response.response.headers, response.response.body, response.response.url); } else { console.log('response not success: %s',response.error.message); //throw new Error(response.error.message || response.error || response); } } }
若是 iPhone 6s 以後的設備(支援免插電源線呼叫 Siri),或是家裡擺一台 Homepod ,就能實現完全不需動手,回到家出一張嘴喊個 Siri 就行了,敲方便。
實際運作影片
成本總結:
- NodeMCU x 1 : NT 120.-
- 紅外線 LED / NPN 電晶體 x1 : 10元 有找
其他必備條件:
- Micro USB 連接線
- 個人電腦一台(撰寫 Arduino Code ,建置 Homebridge 環境)
- 行動電源 或 USB 充電器 或 電腦的 USB 連接埠(可提供 5V USB 連接埠)
- iPhone 手機一支或 iPad(需支援 iOS 10,最低要求為 iPhone 5 / iPad 4th / iPad min)
- 家裡區域網路,與可連上 iCloud 的環境。
補充:
1. 電腦啟動時執行 homebridge(適用於樹莓派)
終端機中執行
$ sudo nano /etc/xdg/autostart/homebridge.desktop
填入以下內容:
[Desktop Entry]
Name=homebridge
Type=Application
Exec=lxterminal -e "homebridge"
Terminal=true
Comment=system monitoring tool.
Categories=Utility;
按 Ctrl + X 存擋離開。
2. 樹莓派升級到 Buster 版本後,nodejs 被強制升級到 10 版,npm 不會隨 nodejs 安裝。用 apt 安裝 npm 的版本是 5.x ,必須升級到 npm 6.x 才能支援 nodejs 10 。
$ sudo apt install npm
$ sudo npm install -g npm@6
3. homebridge 指定網卡服務
以樹莓派 3B/+/4 為例:樹莓派主機上有無線網路和有線網路,homebridge 只能在其中一個網路上啟動。若希望強制在指定的網卡上啟用服務時,必須在 config.json 內指定 mdns 參數,如下
{ "mdns":{ "interface": "網路卡的 IP 位址,例如 192.168.1.100" }, "bridge": { ... 省略... }, }
4. 其他可用插件
4.1 homebridge-http-temperature-sensor (網址)
功能說明:透過網址取得溫度數字。
安裝:
sudo npm install -g homebridge-http-temperature-sensor
config.json 範例
{ "accessory": "HTTP-TEMPERATURE", "name": "裝置溫度", "unit": "celsius", "getUrl": "API 網址", "pullInterval": 5000 }
API 網址回應:溫度浮點數
應用:樹莓派的溫度(讀取 /sys/class/thermal/thermal_zone0/temp 內容並轉換為網址服務)。
留言列表