Domoticz + BroadLink + Synology + Amazon Echo实现智能家居
Overview
此事缘起于在美帝买了Amazon Echo,想着回来可以在家里多说英语,给儿子一些熏陶,也是个大玩具,说不定人家会爱上呢。后来想着整天对Alexa吼这吼那的,如果能唤他帮咱开空调,开电视,开灯,那就不用整天操心遥控器了吗。尤其,整天盯着遥控器的主,拎着遥控器一摇一摆就走了,然后撒着欢儿跑回来,遥控器就不知道丢哪儿了。
首先查到的是BroadLink配件,这其实是一个WiFi转红外+射频的配件。我买的是这个。通过其自带的学习模式,可以学习任何一个遥控器的遥控码。配合Broadlink自家的app就已经可以实现遥控器电子化了。Broadlink有安卓上有两个app:
不够完美的是仍然需要掏出个手机,翻找app,一堆乱点。这不是我想要的。
继续百度,Google,如果要整合Amazon Echo——下文简称Alexa以图方便,有以下几种方案:
- 本身是智能化家居,并且厂家有对应的Skill,enable该Skill即可,好处是各种原生的设置,例如:空调设几度,灯开什么颜色
- 集成BroadLink,让Alexa操作BroadLink,此方案仍然有多种子方案:
1) Android + Broadlink RM Plugin + Alexa
2) Domoticz/Home Assistant + HA-Bridge + Alexa
3) Domoticz + python plugin + controlicz + Alexa
4) Broadlink原生skill + Alexa - Domoticz/Home Assistant + HomeBridge + Siri
其中Domoticz和Home Assistant均为Home Automation System,网上两者都有很多人实践,各有优劣。在参考链接中专门对5种不同的系统进行了比较。因为我有Synology NAS,又可以原生集成,所以毫不犹豫选择了Domoticz。充分发挥NAS 7*24小时不下线的优势,实现智能家庭网关。针对第二点中的后3个(2-4)方案全部进行了实现。后面会一一列述。最终方案架构如下图:
Domoticz into Synology
这个超级简单。有官方支持Domoticz for Synology NAS。选择Domoticz for Synology DSM 6.1 with Python Plugin Beta。python plugin系统很重要,后面会用到。
下载的是.spk文件,这是Synology DSM系统的安装包。直接在Package Center中选择Manual Install即可。安装成功后如下图。
其他依赖包
Domoticz的python插件系统依赖于Python3
broadlink-http-rest server依赖于Python2
HA-Bridge Server依赖于 Java8
最好再装上git,方便checkout GitHub上的开源项目
所以这四个包都得安装,如下图
Broadlink into Domoticz
Domoticz Broadlink Python Plugin + Controlicz
这是本篇中最糟心的部分,陷阱无数。后面专录踩坑记录。
Domoticz Broadlink plugin和broadlink-http-rest均是基于python-broadlink。所以要先安装python-broadlink。
安装python-broadlink
在很多文章中python-broadlink都是用pip来安装,例如pip3 install broadlink
。但是由于broadlink基于pycrypto,而安装pycrypto的时候会要在本地进行编译。Synology NAS上显然没有编译环境(GCC and etc.)。所以安装会失败。但是根据作者的描述,最新的python-broadlink并不基于pycrypto了,因为pycrypto已经被弃坑了。最新的python-broadlink基于pyaes库来实现加解密。所以正确的步骤是:
- 确保使用python3
- git clone python-broadlink
- 切到python-broadlink目录,
python setup.py install
python -m pip install pyaes
因为Synology上无法安装pip3,这是变通的方法。使用python get-pip.py
安装的仍然是pip2
安装Domoticz Python Plugin
参考链接3是插件作者提供的Domoiticz wiki页,不过全文基于Windows,参考其中others章节,仍然很好用。步骤如下:
- 下载plugin files
- Domoticz的插件目录在
/usr/local/domoticz/var/plugins/BroadlinkRM2/
,拷贝插件文件到该目录,包括:- plugin.py ——插件的主文件
- plugin_send.py
- plugin_http.py
- plugin_http.sh
这里需要注意插件目录不是/usr/local/domoticz/plugins/BroadlinkRM2/
,虽然这个目录底下有example目录还有其他插件的目录,但当我把插件文件放在该目录下时,会出现插件未加载的情况。
- 在Synology DSM的Package Center中重启Domoticz。注意后面每次修改plugin都需要重启Domoticz。
至此安装就成功了,直接在Domoticz中添加BroadLink设备如图。
添加Broadlink Hardware
按照插件作者的步骤,下面应该可以添加Hardware,并可以Discover Broadlink设备,添加Hardware如下图:
导入易控(e-control)设备
参考链接3中也有详细描述。在User Guide->Inside Domoticz->xxx - import。可能作者使用的是非多字节语言,在处理导入文件时,若含有中文字,会出现失败的情况。参见踩坑记录中的解决方法。
另外还有一点要注意的是,在点击WebStart以后,Domoticz会开启一个运行于9000的web服务器,用以上传易控的设备文件(jsonButton, jsonIrCode, jsonSubIr)。要注意NAS的Firewall配置。
Controlicz
在搜索到的文章中鲜有提及。我也是在偶然的翻阅中发现了这个Alexa Skill。使用Controlicz就可以不用通过HA-Bridge来曲线救国了。但实际使用中发现还是各有利弊。后文讲完HA-Bridge章节,会提到两者的优缺点。
使用Controlicz的方法是:
- 使用Alexa的账号来注册Controlicz
- Alexa app上enable skill就好了
- 对着Alexa说discover device
注意:Controlcz中要求:
- Domoticz服务必须外网可以访问,所以要配置家里的端口映射,以及DDNS,因为使用的是Synology,这个我早就已经有了
- Controlicz要求Domoticz服务运行于HTTPS协议,所以必须使能8443端口,注意NAS的Firewall配置
- Domoticz服务必须外网可以访问,所以要配置家里的端口映射,以及DDNS,因为使用的是Synology,这个我早就已经有了
踩坑记录
至此,如果能完成上面所有的步骤,对Alexa说”Turn on the TV”,应该已经会有正确响应了。但遗憾的是,中间还有一些东西要做:Import Error “broadlink”
明明已经安装了python-broadlink,而且在REPL中也可以正确import,但是Domoticz log中始终报错。原因是PYTHONPATH不正确。在plugin.py中已有处理:if sys.platform.startswith('linux'):
# linux specific code here
# doesn't work even if set dist-packages => site-packages
sys.path.append(os.path.dirname(os.__file__) + '/dist-packages')
elif sys.platform.startswith('darwin'):
# mac
sys.path.append(os.path.dirname(os.__file__) + '/site-packages')
elif sys.platform.startswith('win32'):
# win specific
sys.path.append(os.path.dirname(os.__file__) + '\site-packages')
正确的broadlink库路径是`/usr/local/lib/python3.5/site-packages/broadlink-0.5-py3.5.egg/broadlink/`。上面linux系统的路径是dist-package。不过即便改成site-packages,依然报同样的错误。解决方法简单明了,将broadlink目录拷到plugins目录下面即可cp -r /usr/local/lib/python3.5/site-packages/broadlink-0.5-py3.5.egg/broadlink/ /usr/local/domoticz/var/plugins/BroadlinkRM2/
Error Connecting to Broadlink device
有两个GitHub issue链接可以看一看:- Error Connecting to Broadlink device #107
- lpad fix broken? #97
或许会有帮助,但对于我的问题不是正解。
Root cause是bytes使用方法不对,错误的地方在这里
# broadlink/__init__.py
160 def encrypt_pyaes(self, payload):
161 aes = pyaes.AESModeOfOperationCBC(self.key, iv = bytes(self.iv))
162 return "".join([aes.encrypt(bytes(payload[i:i+16])) for i in range(0, len(payload), 16)]) # <==== Error is here
python3中bytes返回class bytes,而python2中返回字符串,如下:
Python2
>>> type(bytes([1,2,3]))
<type 'str'>
Python3
>>> type(bytes([1,2,3]))
<class 'bytes'>
>>> "".join([bytes([1,2]),bytes([2,3])]) <==== You cannot cat 2 bytes class objects as string
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: sequence item 0: expected str instance, bytes found
>>> b''.join([bytes([1,2]),bytes([2,3])]) <==== This is the good way
b'\x01\x02\x02\x03'
好了修改plugin.py对应的行就可以了。
Domoticz import文件中有中文的问题
在Python3中,如果文件有编码问题,例如包含中文,不能通过以下方式来读取文件并解码:
with open('jsonFile') as f:
textStr = f.read() <=== Python3 will complain about the codec error here.
textStr.decode('utf8')
正确的做法应当是
with open('jsonFile', encoding='utf8'):
textStr = f.read() <=== Everything here has already been unicode.
所以修改所有plugin.py中的open语句即可。
还有一处要修改的是针对ConfigParser的编码问题。如下是我修改好的:
config = configparser.ConfigParser()
config.read(path, encoding='utf8')
现在试一试,连接,发现,导入,应该都没问题了吧。
Domoticz + broadlink-http-rest + HA-Bridge
这个方案不需要借助Broadlink的Domoticz python插件,而是利用Domoticz中的Dummy Hardware,如下图:
安装HA-Bridge
HA-Bridge是将Alexa不支持的设备模拟成Alexa原生支持的Philips HUE Light。而HA-Bridge可以直接导入Domoticz中的所有设备。缺点是,他只能支持开关和调亮度的操作。
HA-Bridge是一个java的jar包,我们要将之作为service运行在Synology后台,方法参看Run as a service on Synology。
其实就是运行命令nohup java -jar -Dserver.port=8085 /ha-bridge-4.5.6.jar &
注意放到Synology的计划任务里。
安装broadlink-http-rest
从GitHub上clone下broadlink-http-rest。然后和HA-Bridge一样,要以service的方式运行在后台。否则ssh连接一断开,server就退出了。命令为nohup python broadlink-http-rest/server.py &
注意要用nohup,否则serveer仍然会随着ssh断开而退出。
计划任务&防火墙
配置好防火墙:
- 8085: HA-Bridge server
- 8080: broadlink-http-rest server
- 8443: Domoticz HTTPS service
- 9000: Domoticz Broadlink web service
配置好计划任务:
Broadlink into Domoticz
在Setup->Hardware下建立Dummy Hardware,然后点击Create Virtual Sensors,然后在Switches tab里找到刚建好的virtual sensor,点击Edit,按下图配置好On Action和Off Action。
Domoticz into HA-Bridge
参见参考链接2,从Configuring HA bridge开始讲如何配置Domoticz到HA-Bridge service。然后就可以直接添加Domoticz里的设备了。
HA-Bridge vs. Controlicz
General Smart Home
Controlicz可以整合Domoticz所有设备到Alexa中,譬如,如果Alexa并不原生支持该smart home设备,则可以先在家里搭建Domoticz服务器,然后通过Controlicz将之整合到Alexa中。根据Controlicz官网support列表,其并不只局限于开关设备:
整合Broadlink
在整合Broadlink上,两者就各有胜场了。Broadlink是通用遥控器。所以通过Broadlink导入的设备都是按钮设备,每个按钮都是一个Push Button设备,所以只有一个触发的操作。这样也合理,因为按钮只有触发,并没有开状态或者关状态。这甚至不如灯的状态多。
例如:一台电风扇的开关按钮,按一下是开,再按一下是关。如果通过Controlicz直接整合Domoticz按钮设备,则要开电风扇,要对Alexa说“Turn on the Fan”,要关则还是说“Turn on the Fan”。是不是有点奇怪。
如果是HA-Bridge,针对开关状态,就可以说“Turn on the Fan”和“Turn off the Fan”。是不是好多了。
Controlicz整合Domoticz的好处就是,Domoticz Broadlink Python plugin支持直接一次性从易控导入已定义设备,可以充分发挥易控GUI的特点,省得一个一个设备自己定义了。
Broadlink原生Skill + IHC
在整完上面那一大堆之后,我突然发现原来Alexa已经有Broadlink的原生Skill了,但要配合最新版的Broadlink IHC app使用。不过令人糟心的是这两个app的评分都低的可怜。
- IHC playstore 2.2分
- Alexa Broadlink Skill 2.3分
从官网的example看目前只支持TV。经我实践确实如此,添加了电视和空调,Alexa却只能discover到电视,没有空调。