前期
設想
去年寒假前我的房間裏重新上了漆,就買了一臺小米空氣淨化器 2。空氣淨化器通過 WiFi 連接網絡,我可以通過米家 App 管理我的空氣淨化器。但是每次要調空氣淨化器的時候必須要打開米家 App,等上十幾秒再進行操作,着實有點麻煩。尤其是在有 Homekit 的 iPhone 上,這樣的操作總是令人尷尬。
後來發現有 Homebridge 這樣的項目,可以給 Homekit 增加很多自定義功能,包括連接第三方非 Homekit 驗證的智能設備,甚至非智能設備也可以通過插件支持 Homekit 。於是心血來潮,查了很多資料,正好手上有一個樹莓派可以做服務器,let’s begin!
設備
路由器:華碩 AC86U
服務器:樹莓派 3B
智能設備:小米空氣淨化器 2
Homebridge 與 小米空氣淨化器 2 配置過程
固定 IP 地址設置
家用路由通常是打開 DHCP 的,也就是說新的連接設備獲取的 IP 地址是動態的。爲了後面步驟的可行性,一定要先給樹莓派和小米空氣淨化器 2 配置固定的 IP 地址。具體設定步驟可自行谷歌或百度。
樹莓派安裝 Node.js 環境
Homebridge 需要通過 npm 安裝,首先需要配置 Node.js 環境。
SSH 連接至樹莓派,輸入以下安裝 Node.js :
sudo apt-get install nodejs
sudo apt-get install npm
或者源碼安裝的方法也行,可以參考菜鳥教程中 Node.js 的 Ubuntu 安裝方法:https://www.runoob.com/nodejs/nodejs-install-setup.html 。
安裝完成後可以通過以下測試是否安裝成功:
root@Raspberry_Server:~/.homebridge# node -v
v10.7.0
root@Raspberry_Server:~/.homebridge# npm -v
6.1.0
安裝 Homebridge
Homebridge
的 Github :https://github.com/nfarina/homebridge ,裏面講了如何安裝 Homebridge
,不過不是很詳細,我在安裝的時候碰到不少問題,所以多寫一寫詳細過程。
先安裝 Homebridge
:
sudo npm install -g --unsafe-perm homebridge
按照 GitHub 上的說法,--unsafe-perm
是爲了避免出現權限問題,如果沒有這個參數會出現沒有權限的警告:
gyp WARN EACCES user "root" does not have permission to access the dev dir "/root/.node-gyp/5.5.0"
安裝完成後執行:
homebridge
會看到提示:
root@Raspberry_Server:~/.homebridge# homebridge
Couldn't find a config.json file [snip]
Homebridge
的配置文件爲 ~/.homebridge/config.json
,~
爲用戶目錄。如果是默認 pi 用戶,那麼目錄爲 /home/pi
,如果是 root 用戶,那麼目錄爲 /root
。此處建議在 root 下創建這個文件夾,方便後面設置開機啓動。
那麼我就按照 root 用戶的方法繼續:
此時在 root 用戶下創建配置文件,並用 Vim 編輯器編輯:
cd ~
mkdir .homebridge
vim config.json
在文件中添加:
{
"bridge":{
"name": "Homebridge",
"username": "CC:22:3D:E3:CE:30",
"port": 51826,
"pin": "031-45-154"
},
"description": "This is my homebridge",
}
這是一個 json 格式的文件,可以看到 bridge
下有幾個對象,其中:
name
:這個配件在 Homekit 中顯示的名字
username
:一個類似於 MAC 地址的字段,按默認的填寫就行
port
: Homekit 的通訊端口,採用 TCP 協議,確保樹莓派的這個端口開放即可
pin
: iPhone 在 Homkit 中配對時的配對碼,在後面操作中配對的時候可以掃描二維碼配對,可以不用刻意記住
description
: 隨便寫什麼都可以,好像也沒在哪裏能再看到它了….
那麼到這裏 Homebridge
就算是配置完了,接下來要給 Homebridge
安裝插件,讓它支持我的小米空氣淨化器 2。
安裝 homebridge-mi-air-purifier 插件
homebridge-mi-air-purifier
插件的 GitHub :https://github.com/seikan/homebridge-mi-air-purifier
homebridge-mi-air-purifier
插件可以通過 npm 安裝,同時它也依賴 miio
插件,因此需要安裝兩個插件:homebridge-mi-air-purifier
和 miio
:
npm install -g homebridge-mi-air-purifier miio
讓小米空氣淨化器 2 和樹莓派連接在同一局域網內,然後通過 miio
命令獲取空氣淨化器的信息:
miio discover --sync
然後等待一會,出現下面的信息:
Device ID: 49466088
Model info: Unknown
Address: 192.168.1.8
Token: 6f7a65786550386c700a6b526666744d via auto-token
Support: Unknown
記下 Address 和 Token 的值,然後修改 Homebridge
的配置文件 ~/.homebridge/config.json :
{
"bridge":{
"name": "Homebridge",
"username": "CC:22:3D:E3:CE:30",
"port": 51826,
"pin": "031-45-154"
},
"description": "This is my homebridge",
"accessories": [
{
"accessory": "MiAirPurifier",
"name": "Bed Room Air Purifier",
"ip": "192.168.1.8",
"token": "6f7a65786550386c700a6b526666744d",
"showTemperature": true,
"showHumidity": true,
"showAirQuality": true,
"showLED": true,
"showBuzzer": true
}
]
}
在 accessories
中的每個對象裏都有這幾個鍵值對,其中:
acccessory
:配件的型號或者標識,不可更改。
name
:在 Homekit 中顯示的名字,可以自行更改。
ip
:空氣淨化器的 IP 地址,即上一步中需要記下的 Address 。
token
:空氣淨化器的 Token ,即上一步中需要記下的 Token。
showTemperature
:是否顯示溫度,填 true
或 false
。
可以看到 accessories
是一個數組 ,也就是說它支持添加多個配件。如果有兩個空氣淨化器,配置文件可以這麼寫:
{
"bridge":{
"name": "Homebridge",
"username": "CC:22:3D:E3:CE:30",
"port": 51826,
"pin": "031-45-154"
},
"description": "This is my homebridge",
"accessories": [
{
"accessory": "MiAirPurifier",
"name": "Bed Room Air Purifier",
"ip": "192.168.1.8",
"token": "6f7a65786550386c700a6b526666744d",
"showTemperature": true,
"showHumidity": true,
"showAirQuality": true,
"showLED": true,
"showBuzzer": true
},
{
"accessory": "MiAirPurifier",
"name": "NAME_OF_AIR_PURIFIER",
"ip": "IP_ADDRESS_OF_AIR_PURIFIER",
"token": "TOKEN_OF_AIR_PURIFIER",
"showTemperature": true,
"showHumidity": true,
"showAirQuality": true,
"showLED": true,
"showBuzzer": true
}
]
}
以此類推。
接下來添加其他的配件,也是需要在數組中添加對象,只不過不同類型的配件,對象中的鍵值對不盡相同。
那麼到這裏 Homebridge
已經成功與小米空氣淨化器 2 連接,接下來就讓 iPhone 接入令人興奮的家庭應用吧!
iPhone 與 Homebridge 連接
首先在 iPhone 上打開家庭應用,點擊開始使用,然後點擊加入配件:
然後在樹莓派的 SSH 中輸入:
homebridge
如果工作正常,應該會有如下顯示:
root@Raspberry_Server:~# homebridge
[8/2/2018, 7:00:22 AM] Loaded config.json with 1 accessories and 0 platforms.
[8/2/2018, 7:00:23 AM] ---
[8/2/2018, 7:00:25 AM] Loaded plugin: homebridge-mi-air-purifier
[8/2/2018, 7:00:25 AM] Registering accessory 'homebridge-mi-air-purifier.MiAirPurifier'
[8/2/2018, 7:00:25 AM] ---
[8/2/2018, 7:00:25 AM] Loading 1 accessories...
[8/2/2018, 7:00:25 AM] [Air Purifier] Initializing MiAirPurifier accessory...
Setup Payload:
X-HM://0023UTGR67DPM
Scan this code with your HomeKit app on your iOS device to pair with Homebridge:
--------------------
--------------------
--------------------
--------------------
--------------------
--------------------
Or enter this code with your HomeKit app on your iOS device to pair with Homebridge:
┌────────────┐
│ 031-45-154 │
└────────────┘
[8/2/2018, 7:00:25 AM] Homebridge is running on port 51826.
Discovered Mi Air Purifier (zhimi.airpurifier.m1) at 192.168.1.8
上面那六行短橫線是一個二維碼,在應用中掃描二維碼後,選擇仍然添加:
然後就是一堆配件啦,瘋狂點擊下一步添加:
那麼最終顯示的界面大概是這樣的:
到這裏就成功地把小米空氣淨化器 2 接入 Homebridge
並且在家庭應用中顯示啦!
設置開機啓動
Homebridge
在運行之後不能關閉 SSH 窗口,不然就會自動關閉。那麼爲了讓 Homebridge
在開機的時候自動啓動並且後臺運行,需要爲它設置開機啓動。爲了方便查看 Homebridge
的運行狀態,我想讓 Homebridge 的輸出內容寫入日誌文件,在我需要的時候可以打開查看狀態。那麼我這裏用 nohup 命令,讓 Homebridge 後臺運行並寫入日誌:
sudo nohup homebridge > /var/log/homebridge.log 2>&1 &
設置開機啓動有多種方式,可以自行谷歌或百度。在這裏我選擇修改 /etc/rc.local 文件:
sudo vim /etc/rc.local
在 exit 0 前添加一行代碼:
sudo nohup homebridge > /var/log/homebridge.log 2>&1 &
這樣就可以讓 Homebridge 開機啓動,並且自動將輸出內容寫入日誌文件,便於日後維護。
小結
到這裏基本的配置就結束啦!其實仔細看,我的主界面不止有小米空氣淨化器 2 的配件,還有我的華碩 AC86U 路由器幾個重要部件的溫度顯示。如果只想把空氣淨化器接入,那麼這篇文章就到此爲止啦。但如果你的路由器也是華碩 AC86U ,或者自己也想搞一個溫度顯示,那麼可以繼續往下看,參考我的做法。
讓 Homebridge 告訴我 AC86U 的體溫
實現構思
要想在 Homekit 中查看 AC86U 的體溫,首先需要知道如何獲取 AC86U 的溫度。在華碩路由論壇(http://www.52asus.com)中查找相關資料,很快找到了方法:
(論壇鏈接:http://www.52asus.com/thread-3819-1-1.html)
在 AC86U 上執行命令:
核心溫度:cat /sys/class/thermal/thermal_zone0/temp
2.4G溫度:wl -i eth5 phy_tempsense
5G溫度:wl -i eth6 phy_tempsense
那麼知道了如何獲取 AC86U 的溫度之後,就要讓 Homebridge
能夠獲取這個溫度。
Homebridge
有個插件 homebridge-http-temperature-humidity
,可以通過 HTTP 的 GET
請求從服務器獲取溫度和溼度,那麼我現在需要做的,就是搭建一個服務器,能 Telnet
到我的 AC86U,獲取溫度並返回給 Homebridge
。
爲了方便,我用樹莓派做服務器,用 Apache 2。服務器腳本用 Python 編寫,通過 Telnet
到 AC86U 返回數值,我用的版本是 Python 3.5。
知道了如何實現之後,接下來就是實戰了。
編寫腳本
編寫腳本需要有一點點 Python 基礎即可,沒有什麼需要特別多說的。
但是有一點需要說明的是,腳本是通過一個名爲 application
的函數與服務器建立交互的,其中形參有 environ
和 start_response
,返回值就是服務器返回的數據。
#!/usr/bin/env python
#coding=utf-8
def application(environ, start_response):
output = 'test'
status = '200 OK'
response_headers = [('Content-type', 'text/plain'),('Content-Length', str(len(output)))]
start_response(status, response_headers)
return output
根據 homebridge-http-temperature-humidity
插件的說明,返回值是 json 格式,包含兩個對象:temperature
和 humidity
。這裏沒有溼度的數據,所以返回的內容只需包含 temperature
即可。
爲了方便,這裏給出了獲取 CPU 溫度的腳本 cputemp.wsgi
,獲取 2.4G 和 5G 溫度的可以根據以下修改:
#!/usr/bin/env python
#coding=utf-8
def application(environ, start_response):
import telnetlib
Host = '192.168.1.1'
username = 'username'
password = 'password'
tn = telnetlib.Telnet(Host, port=23, timeout=10)
tn.read_until('login:'.encode('utf-8'))
tn.write((username + '\n').encode('utf-8'))
tn.read_until('Password:'.encode('utf-8'))
tn.write((password + '\n').encode('utf-8'))
tn.read_until('#'.encode('utf-8'))
tn.write(('cat /sys/class/thermal/thermal_zone0/temp'+'\n').encode('utf-8'))
tn.read_until('\n'.encode('utf-8'))
temp = tn.read_until('\n'.encode('utf-8'))
temp_i = int(temp[:5])
temp_i = round(temp_i/1000)
output = '{"temperature": ' + str(temp_i) + '}'
tn.close()
status = '200 OK'
response_headers = [('Content-type', 'text/plain'),('Content-Length', str(len(output)))]
start_response(status, response_headers)
return output
其中 Host
是路由器的局域網 IP 地址,username
是 Telnet 的用戶名,password
是 Telnet 的密碼。
腳本中有很多小細節是針對路由器寫的。如果你的路由器不是 AC86U ,那麼這個腳本很可能不能正常運作。有編程基礎的讀者可以自行鍼對路由器修改。
配置服務器
我的樹莓派已經裝好了 Apache 2 和 Python 3.5。爲了讓 Apache 運行 Python 腳本,需要安裝 WSGI 模塊:
sudo apt-get install libapache2-mod-wsgi
sudo apt-get install libapache2-mod-wsgi-py3
WSGI 安裝完成後默認是啓用 WSGI 模塊的。爲了確保正常運行,可以看下 /etc/apache2/mods-enabled
目錄下有沒有 wsgi.conf
和 wsgi.load
。如果沒有,從 mods-available
中 ln -s
或 cp
到 mods-enabled 目錄下。
腳本我放在 /var/www/homebridge
下,你也可以選擇不同的目錄,在配置服務器的時候更改相應目錄即可。
現在配置服務器,讓服務器能執行我的腳本。
vim /etc/apache2/apache2.conf
首先要給 /var/www/homebridge
賦予權限:
<Directory /var/www/homebridge/>
AllowOverride None
Options +ExecCGI
Require all granted
</Directory>
然後鏈接服務器訪問地址和腳本文件:
WSGIScriptAlias /homebridge/cputemp /var/www/homebridge/cputemp.wsgi
WSGIScriptAlias /homebridge/2.4G_temp /var/www/homebridge/2.4G_temp.wsgi
WSGIScriptAlias /homebridge/5G_temp /var/www/homebridge/5G_temp.wsgi
可以看到在 /var/www/homebridge
下,腳本文件名分別是 cputemp.wsgi
,2.4G_temp.wsgi
,5G_temp.wsgi
。
添加完成以上內容之後,我把這幾個腳本寫好放入 /var/www/homebridge
,重啓 Apache:
service apache2 restart
爲了可行,可以先用手機或電腦瀏覽器訪問樹莓派,查看服務器是否能返回正確的 json。到此服務器和腳本就已經配置完成了。
Homebridge 配置插件
如上文所述,Homebridge
插件配置非常簡單,只需在 config.json
中添加內容即可。
accessories
對象下內容:
"accessories":[
{
"accessory": "MiAirPurifier",
"name": "Air Purifier",
"ip": "192.168.1.8",
"token": "6f7a65786550386c700a6b526666744d",
"showTemperature": true,
"showHumidity": true,
"showAirQuality": true,
"showLED": true,
"showBuzzer": true
},
{
"accessory": "HttpTemphum",
"name": "AC86U CPU Temperature",
"url": "http://localhost/homebridge/cputemp",
"httpMethod": "GET",
"humidity": false,
"cacheExpiration": 60
},
{
"accessory": "HttpTemphum",
"name": "AC86U 2.4G Model Temperature",
"url": "http://localhost/homebridge/2.4G_temp",
"httpMethod": "GET",
"humidity": false,
"cacheExpiration": 60
},
{
"accessory": "HttpTemphum",
"name": "AC86U 5G Model Temperature",
"url": "http://localhost/homebridge/5G_temp",
"httpMethod": "GET",
"humidity": false,
"cacheExpiration": 60
}
]
在 accessory
值爲 HttpTemphum
的對象中有以下幾個鍵值對:
name
:傳感器名稱,可更改。
url
:服務器訪問地址。在這裏 Homebridge
和服務器均爲樹莓派,所以可以用 localhost
代替 IP 地址。
httpMethod
:HTTP 請求方式,填 GET
。
humidity
:是否顯示溼度,這裏填 false
。
cacheExpiration
:數據的存儲週期,單位:秒。如果不清楚這個鍵值的作用,填 60
即可。
到這裏之後有一個關鍵步驟,否則會出現配件無響應,或者重新連接家庭應用的時候,提示要重置配件。
在每次更改 config.json
並使更改生效前,需要清理 ~/.homebridge
下除了 config.json
的其他文件,這裏需要清理的文件有兩個文件夾: accessories
和 persist
。
cd ~/.homebridge
rm -rf accessories persist
刪除之後重新啓動樹莓派:
sudo reboot
按照上文的配對步驟,讓 iPhone 重新配對一下即可。
後記
這篇文章編寫前,我對這個 Homekit 是垂涎已久,網上也有不少教程,但有的細節沒有給出,導致實現過程磕磕絆絆,花了不少時間。所以想寫一篇文章,不僅僅是記錄這個實現的過程,也是爲了更多人能花更少的時間,走更少彎路。第一次寫博客,不足之處敬請諒解,若有錯誤請指正,或有不夠詳盡之處請指出。
參考鏈接:
Node.js 安裝:https://www.runoob.com/nodejs/nodejs-install-setup.html
Homebridge GitHub :https://github.com/nfarina/homebridge
homebridge-mi-air-purifier 插件 GitHub :https://github.com/seikan/homebridge-mi-air-purifier
homebridge-http-temperature-humidity 插件 GitHub :https://github.com/lucacri/homebridge-http-temperature-humidity
Terry’s Blog :https://blog.terrychan.me/2017/homekit-and-homebridge
華碩 AC86U 獲取溫度:http://www.52asus.com/thread-3819-1-1.html
WSGI Python 腳本程序:https://www.cnblogs.com/Erick-L/p/7063173.html (Apache 2 配置部分不適用)
nohup 用法:https://www.cnblogs.com/jinxiao-pu/p/9131057.html