El Psy Congroo

小米网关接入Homekit

前段时间买了一堆小米的ZigBee智能设备回来玩,从硬件来讲,无论性价比还是设计做工都诚意满满,值得安利,虽然硬件本身并没有太多新意,以前也有很多类似产品,但是配合小米不断壮大的智能设备生态圈,可玩性是别的品牌不能比拟的,嗯,我在说贝尔金的Wemo…

米家App的功能也还不错,但是和以前用的Wemo比起来主要有两个问题

  • 不支持局域网控制,所有操作都是要去服务端绕一圈的,如果服务器挂了或者断网了…
  • 不提供API,无法与外部设备或应用联动,例如无法接入IFTTT

在搜索API的过程中,偶然发现了这篇文章,小米网关接入Homekit完整教程,感觉打开了新世界的大门,教练,我也想打篮球接入Homekit

关于HomeKit和homebridge

HomeKit本身也是个封闭平台,只授权给MFi认证的公司,并且需要在设备中安装专门的ID芯片,这样严格的限制的确有利于提供一致的用户体验(例如AirPlay),但也阻碍了智能设备的普及,参考Apple官网那些HomeKit配件价格,这么贵怎么愉快的玩耍……

所幸的是,有黑客通过对HomeKit协议的逆向工程,写了HAP-NodeJS这个项目,可以通过nodejs来模拟HomeKit设备,基于这个项目,最终才有了homebridge。

Homebridge是一个轻量级的NodeJS server,模拟成一个HomeKit网关,通过插件方式将第三方智能设备的API桥接为HomeKit协议,现在npm上已经有数百个插件了,包括支持小米智能网关的homebridge-aqara,以及支持Yeelight智能灯的homebridge-yeelight

安装homebridge

在Mac上安装

在Mac上安装最简单,直接npm install -g homebridge --unsafe-perm就搞定了,可惜并没有壕到可以在家放一台Mac当server,也没有折腾过树莓派,只能考虑装在NAS上了。

在Linux上安装

在Linux上安装的话,需要依赖libavahi-compat-libdnssd-dev,先简单介绍下Avahi

关于Avahi

Avahi是Linux上Zeroconf规范的开源实现,通过Multicast DNS(mDNS)来实现零配置的服务发现DNS-Based Service Discovery(DNS-SD),另一个知名实现就是Apple的Bonjour,这个规范其实就是Apple提出的。下面简单介绍下命名和发现部分的基本原理。

命名

Bonjour定义了一套命名规则,对主机和服务进行命名,本地主机使用local.这个伪域名,例如myserver.local.,服务命名的规则如下

_ServiceType._TransportProtocolName.

1
2
3
4
//例如:
_airplay._tcp
_ssh._tcp
_hap._tcp //HomeKit Accessory Protocol
发现

DNS-SD使用224.0.0.251这个多播地址来注册及发现服务,mDNS并不需要独立的DNS服务器,当需要解析时,直接向224.0.0.2515353端口发送查询请求,组内收到请求的设备判断自己是否满足查询条件并自行回复

Mac下可以直接使用dns-sd命令来查询服务,例如列出本地网络中的ssh服务:

1
2
3
4
5
6
7
8
9
$ dns-sd -Z _ssh._tcp
_ssh._tcp PTR hellfires-mbp._ssh._tcp
hellfires-mbp._ssh._tcp SRV 0 0 22 hellfires-mbp.local. ; Replace with unicast FQDN of target host
hellfires-mbp._ssh._tcp TXT ""
_ssh._tcp PTR hai._ssh._tcp
hai._ssh._tcp SRV 0 0 22 hai.local. ; Replace with unicast FQDN of target host
hai._ssh._tcp TXT ""

也可以使用dig来查询,不过由于DNS协议规范,dig只会返回第一条查询结果

1
2
# 注册到mDNS上的ptr记录是服务名加上.local.
$ dig @224.0.0.251 -p 5353 -t ptr _ssh._tcp.local

想了解更多可以参考这篇Blog,以及RFC文档RFC 6762 (mDNS)RFC 6763 (DNS-SD)

在QNAP上安装homebridge完整过程

家里的NAS是QNAP的,当然群晖的也没问题,反正最终是通过docker安装的,可以免去处理一堆依赖的麻烦

下载镜像

首先确认Container Station已经安装好
在Container Station中下载marcoraddatz/homebridge这个镜像,或者直接ssh登录后docker pull marcoraddatz/homebridge,这个镜像已经安装好了homebridge和avahi,只需要mount上配置文件就可以使用了

编辑配置文件

在NAS上新建一个目录,用于放置homebridge相关配置,这边假设是/path_to_folder/homebridge,在目录中新建两个文件

config.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"bridge": {
"name": "Homebridge",
"username": "11:22:33:44:55:66",
"port": 51826,
"pin": "031-45-154"
},
"platforms": [
{
"platform" : "yeelight",
"name" : "yeelight"
},
{
"platform": "AqaraPlatform",
"sid": ["f0b429cc3a65"],
"password": ["F8DF6CD6FA5345C3"]
}]
}

bridge homebridge配置

  • name,在Home App中显示的设备名称,随意填写,可以重复
  • username,设备唯一ID,格式如上,内容随意填写,但不可以重复,如果Home App中无法找到这个homebridge设备,可以尝试更换username
  • pin,在Home App中配对用的,格式如上,内容随意设置

platforms 插件配置

  • yeelight,适配Yeelight灯具的插件,包括小米台灯(需要最新固件)
  • AqaraPlatform,适配绿米网关(小米网关生产厂商)的插件
    • sid,网关mac地址
    • password,局域网通信协议密码

sid与password的获取方式:
a. 在米家App中进入网关设备页面
b. 页面右上角菜单进入关于页面
c. 连续点击下方空白处,启用开发者模式
d. 进入局域网通信协议菜单,打开开关并记录下密码,填入password字段
e. 进入网关信息菜单,找到mac=开头的mac地址,注意不是gw_mac,去掉:填入sid字段

install.sh

配置需要安装的插件,暂时只添加了小米和Yeelight的,可以按需增加,新建容器时会读取这个配置并安装

1
2
3
4
#!/bin/bash
npm install -g homebridge-yeelight
npm install -g homebridge-aqara

启动容器

注意替换/path_to_folder/homebridge为实际路径

1
docker run -d --name homebridge --net=host -p 5353:5353/udp -p 51826:51826 -v /path_to_folder/homebridge:/root/.homebridge marcoraddatz/homebridge

不出意外的话,应该能看到如下日志,表明已经启动成功了,打开Home App添加设备吧~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[3/14/2017, 2:05:16 PM] Loaded plugin: homebridge-aqara
[3/14/2017, 2:05:16 PM] Registering platform 'homebridge-aqara.AqaraPlatform'
[3/14/2017, 2:05:16 PM] ---
[3/14/2017, 2:05:16 PM] Loaded config.json with 0 accessories and 1 platforms.
[3/14/2017, 2:05:16 PM] ---
[3/14/2017, 2:05:16 PM] Loading 1 platforms...
[3/14/2017, 2:05:16 PM] Initializing AqaraPlatform platform...
Scan this code with your HomeKit App on your iOS device to pair with Homebridge:
┌────────────┐
│ 031-45-154 │
└────────────┘
[3/14/2017, 2:05:16 PM] Homebridge is running on port 51826.

常见问题

如果Home App中无法找到homebridge网关的话,一般有两个问题

  • Homebridge认为已经配对成功,而iOS那边其实失败了,由于homekit设备只能和一台iOS配对,因此iOS无法发现已经配对过的homebridge,解决方法是删除.homebridge/目录中的persist/目录
  • 前面提到的username问题,可能是重复了,也可能是iOS设备中有异常,解决方法是随便换一个

外网访问

HomeKit默认只能在局域网内使用,如果要在外网访问的话,需要家里有第四代的Apple TV或者任意iPad做中转,如果是iPad的话,在Settings -> Home中开启Use this iPad as a Home Hub即可,不过国内这网络中转速度实在感人…

最后

当然不能忘了调戏下Siri

"Turn off the Blueair in the Living Room"

OK, the Blueair is off.

"Temperature in the Living Room"

The Living Room temperature in My Home is at 17℃.