去年寒假前我的房间里重新上了漆,就买了一台小米空气净化器 2。空气净化器通过 WiFi 连接网络,我可以通过米家 App 管理我的空气净化器。但是每次要调空气净化器的时候必须要打开米家 App,等上十几秒再进行操作,着实有点麻烦。尤其是在有 Homekit 的 iPhone 上,这样的操作总是令人尴尬。
后来发现有 Homebridge 这样的项目,可以给 Homekit 增加很多自定义功能,包括连接第三方非 Homekit 验证的智能设备,甚至非智能设备也可以通过插件支持 Homekit 。于是心血来潮,查了很多资料,正好手上有一个树莓派可以做服务器,let’s begin!
路由器:华硕 AC86U
服务器:树莓派 3B
智能设备:小米空气净化器 2
家用路由通常是打开 DHCP 的,也就是说新的连接设备获取的 IP 地址是动态的。为了后面步骤的可行性,一定要先给树莓派和小米空气净化器 2 配置固定的 IP 地址。具体设定步骤可自行谷歌或百度。
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
的 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
插件的 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 上打开家庭应用,点击开始使用,然后点击加入配件:
然后在树莓派的 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 ,或者自己也想搞一个温度显示,那么可以继续往下看,参考我的做法。
要想在 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
插件配置非常简单,只需在 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