目标
使用开源软件和米家智能硬件,实现简单的智能家居系统
采用米家智能硬件的原因是, 小米智能家居做的比较早(也许是起初推广的更好,刚接触智能家居的时候就用的小米), 另外一点是小米智能硬件确实物美价廉,在国外也很受欢迎,Github上也有很多相关项目.
环境和设备
- RaspberryPi 4 (4GB版本)
- Ubuntu arm64 树莓派版本
安装HomeAssistant
这里使用Ubuntu而不是Raspbian的一个原因是Ubuntu官方软件包更新更快(比如raspbian当前为3.7而hass需要3.8+版本), 且自己笔记本一直用Ubuntu,统一发行版使用起来更加方便
sudo pip3 install homeassistant
如果下载很慢,可以考虑使用pypi镜像源
编辑/etc/pip.conf
(使用豆瓣源)
[global]
index-url = https://pypi.douban.com/simple
设置开机自启动
- 创建systemd service unit文件
systemctl --user edit --full --force homeassistant.service
加入以下内容
[Unit]
Description=Home Assistant
After=network.target
[Service]
Type=simple
ExecStart=/home/ubuntu/.local/bin/hass
Restart=on-failure
RestartSec=5
[Install]
WantedBy=default.target
- 设置用户自动登录
安装raspi-config
,
然后配置 1. System Options
-> S5 Boot / Auto Login
-> B2 Console Autologin
会生成/etc/systemd/system/getty@tty1.service.d/autologin.conf
, 内容如下
[Service]
ExecStart=
ExecStart=-/sbin/agetty --autologin ubuntu --noclear %I $TERM
重启即可生效
常用设备接入
这里主要使用小米硬件设备,开始之前需要获取各个设备的token。参考homeassistant获取miio token的教程
目前推荐使用云端获取的方式 https://github.com/PiotrMachowski/Xiaomi-cloud-tokens-extractor
- homeassistant 参考配置
.homeassistant/configuration.yaml
# Configure a default setup of Home Assistant (frontend, api, etc)
default_config:
homeassistant:
allowlist_external_dirs:
- "/mnt/usb/media"
media_dirs:
local: /mnt/usb/media
# Text to speech
tts:
- platform: google_translate
rpi_camera:
image_quality: 100
timelapse: 5000
file_path: /mnt/usb/media/camera/snapshot.jpg
group: !include groups.yaml
automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml
light: !include lights.yaml
yeelight: !include yeelight.yaml
remote: !include remote.yaml
stream:
media_player: !include media_player.yaml
device_tracker: !include device_tracker.yaml
shell_command: !include shell.yaml
telegram_bot: !include telegram.yaml
notify: !include notify.yaml
插座/灯泡
小米插座chuangmi.plug.m1
和灯泡(这里我用的是飞利浦灯泡), 使用[python miio]即可以控制。
可以在homeassistant管理界面添加Xiaomi Miio
集成。
网关
小米网关提供了ZigBee和蓝牙设备接入和管理的功能。
型号: lumi.gateway.mgl03
升级官方新版本固件后,不能直接接入。可以刷入第三方固件,然后接入homeassistant。
- 刷机
telnet登录网关,按照GitHub上的此教程执行刷机步骤
如果访问不了Github下载链接,可以使用代理,例如设置环境变量
https_proxy=socks5://192.168.50.60:1080
红外遥控器
红外遥控器也可以使用xiaomi_miio
接入homeassistant。
型号: chuangmi.remote.v2
配置示例remote.yaml
(示例里的raw command我瞎填的, 根据自己的实际需要写)
- platform: xiaomi_miio
name: 'chuangmi.remote.v2'
host: 192.168.50.72
token: <token>
slot: 1
timeout: 30
hidden: false
commands:
# haier
air_conditioner_turn_on:
command:
- raw:mcwm84lgAkzSazOcSyazScSyYzacTYAhAA3AQ8BjwIfAZ8DfwIfAh8APwA:38400
air_conditioner_turn_off:
command:
- raw:mcwm84lgAkzSazOcSyazScSyYzacTYAhAA3AQ8BjwIfAQ8BDwO/Bd8APwA/AD8APwA/AD8APwA/AD8AP:38400
air_conditioner_cool:
command:
- raw:mcwm84lgAkzSazOcSyazScSyYzacTYAhAA3AQ8BjwIfAQ8BDwO/Bd:38400
magic_ball_turn_on:
command:
- raw:nMxm8wlk0mk2mEsm0ymEsmsxAHKYADlMwB2mgB/ADmBP4B9TGbAYMAR4BFApoBmUxAEMAjwNPA0gJCwcHCI8A/wJ6BjoKrwCOCHuYQA=
magic_ball_turn_off:
command:
- raw:nMxmswlk0mk4mEsm0ymEsmsxAHKYADlNAD+mYA9AL+APUxmwHDTGbAQsAjQAhAdwAhYBCgV2BFoR7g/+Ae01nID/g2cBAYLShH+AjQDXgEJMIAA=
然后我们可以在scripts.yaml
里定义常用的操作(这些操作可以在安卓的设备控制器快捷方式找到)
'air_conditioner_turn_on':
alias: '打开空调(睡眠模式)'
sequence:
- service: remote.send_command
entity_id: 'remote.chuangmi_remote_v2'
data:
command:
- 'air_conditioner_turn_on'
'air_conditioner_turn_off':
alias: '关闭空调'
sequence:
- service: remote.send_command
entity_id: 'remote.chuangmi_remote_v2'
data:
command:
- 'air_conditioner_turn_off'
'air_conditioner_cool':
alias: '空调制冷'
sequence:
- service: remote.send_command
entity_id: 'remote.chuangmi_remote_v2'
data:
command:
- 'air_conditioner_cool'
'magic_ball_turn_on':
alias: '打开小夜灯'
sequence:
- service: remote.send_command
entity_id: 'remote.chuangmi_remote_v2'
data:
command:
- 'magic_ball_turn_on'
'magic_ball_turn_off':
alias: '关闭小夜晚灯'
sequence:
- service: remote.send_command
entity_id: 'remote.chuangmi_remote_v2'
data:
command:
- 'magic_ball_turn_off'
效果如下
学习红外码
接入遥控器后,我们可以通过它学习红外码。进入开发者工具 -> 服务,选择xiaomi_miio.remote_learn_command
点击调用服务,然后把遥控器对准米家万能遥控器按下要学习的按键,就可以学习了。识别的红外码会出现在homeassistant
的通知那里, 可以配置到上面yaml的raw command
。(在使用前,可以用remote.send_command
测以下)
刚好别人送我一个小夜灯,试了一下,可以智能地控制了。
Hack红外码
使用xiaomi_miio.remote_learn_command
方式只能学习简单的红外码。对于复杂的红外码,比如空调,遥控器学习识别的红外码不起作用
(我傻乎乎地尝试了好久才发现这个知识)
解决方式之一是, 你知道空调的各个按键的raw command是什么,即使用红外码库。查了一下,国外有一些开源的红外码库,但没有国内的设备型号, 而且设备类型比较少。
我使用的是海尔空调,只找到https://github.com/crankyoldgit/IRremoteESP8266库,可能有可以利用的信息(有测试代码), 但是它使用的是pronto格式,支持的设备类型也有限。
后面发现了硬核的hack方式, 可以通过串口连上遥控器的控制台,从调试日志中获取红外码。
这里简单说一下步骤。
- 焊接
对于一个新手来说,焊接PCB板是一个比较麻烦的事情。基于大学时,曾焊接制作过一个完整收音机的经历,我开始动手了。
如图,拆完后焊点是PCB板上的三个圆形金属接触点(TX, RX, GND)。可能不是设计用来焊接的(我猜测应该是有专门的金属探头压在上面,使电路接通),先要将 导线镀焊,不然焊接会颇为麻烦, 不太容易焊上。
PS, 虽然焊接这个成功了,但是小米台灯焊接后却没能连上, 不过它可以接入到Google Home,作为一个桌面上的台灯也没必要太多的智能控制场景了
- 串口调试
连接好USB串口线后,启动电源。
在笔记本上安装好screen
软件, 执行以下命令
screen -L /dev/ttyUSB0 115200
# Ctrl + A + : 打开screen菜单
日志将输出到screenlog.0
, 随着你在米家App上按下空调键,可以从中看到有用的日志信息(token)。
这里给出部分日志(被我删除处理过敏感信息了)
------Now net status:4------
23:06:44.740 [D] otu: [192.168.50.32:51222] talking, len=32
23:06:44.740 [W] otu: Token private!!. (otu_packet_handle,706)
23:06:44.750 [D] otu: [192.168.50.32:51222] talking, len=32
23:06:44.750 [W] otu: Token private!!. (otu_packet_handle,706)
23:06:44.760 [D] otu: [192.168.50.32:51222] talking, len=32
23:06:44.760 [W] otu: Token private!!. (otu_packet_handle,706)
23:06:44.770 [D] otu: [192.168.50.32:57072] talking, len=304
23:06:44.780 [D] otu: local rpc packet.
23:06:44.780 [D] otu: {"id": 43, "method": "miIO.ir_play", "params": {"freq": 38400, "code": "mcwm84lgAkzSazOcSyazScSyYzacTYAhAA3AQ8BjwIfAQ8CrwCPAr8APwA/AD8APwA/AD8APwA/AD8APwA/AD8APwA/AD8APwA/AD8APwA"}}.
23:06:44.810 [D] otu: down rpc_local = 7
23:06:44.810 [D] ot: miIO.ir_play found
------do_ir_play cmd:{"id": 43, "method": "miIO.ir_play", "params": {"freq": 38400, "code": "mcwm84lgAkzSazOcSyazScSyYzacTYAhAA3AQ8BjwIfAQ8CrwCPAr8APwA/AD8APwA/AD8APwA/AD8KDwA/AD8APw6vAh8APwA"}}------
ir_play:Cannot found length
Base64Decode------------>len=143
99,cc,26,f3,89,60,2,4c,d2,6b,33,9c,4b,26,b3,49,c4,b2,63,36,9c,4d,80,21,0,d,c0,43,c0,63,c0,87,c0,43,c0,ab,c0,23,c0,af,c0,f,c0,f,c0,f,c0,f,c0,f,c0,f,c0,f,cf,c0,f,c0f,c0,f,c0,f,c0,f,c0,f,c2,27,c0,53,c0,f,c0,f,c0,f,c0,f,c0,f,c0,f,c0,f,c0,f,c0,f,c0,f,c0,f,c0,f,c0,f,c0,f,c0,f,c0,f,c0,f,c0,f,c0,f,c0,f,c5,63,c0,f,c0,a3,c0,a3,c8,93,c0,87,e6,33,9,84,c0,
Base64Decode------------>end
tmp_ct=941
23:06:44.880 [I] user_main: ----origin_code:3078,3078,3078,4,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,1686,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,1686,548,1686,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,1686,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,1686,548,548,548,548,548,548,548,548,548,1686,548,548,548,548,548,1686,548,1686,548,548,548,1000
23:06:44.970 [I] splitnums=230
23:06:44.970 [I] item nums=120
last = 1000
wave_data_len=115
-----------------------------
-----send_infrared_fro23:06:m_buf--
len=115
0~2456,1~2456||0~2456,1~3644.990 24||0~432,1~1344||0~432,1~432||0~432,1~1344||0~4[D] otu: {"id":43,"result":["ok"]}
32,1~432||0~432,1~432||0~432,1~1344||0~432,1~1344||0~432,1~432||23:06:45.010 [D] otu
0~432,1~1344||0~432,1~432||0~432,1~1344||0~432,1~1344||0~432,1~1344||0~432,1~1344||0~
日志中的code
部分就是红外码了。
和来源的作者一样,我这里也告警一下,红外码库可能涉及到授权和购买, 不要用作商业用途和违法事情
Telegram通知
完成了硬件设备的接入,我们还需要实现自动监控和远程控制。
除了将API托管到云端,还可以通过邮件或者IM工具实现。这里Telegram机器人就可以满足这个需求了。
配置
telegram.yaml
- platform: polling
proxy_url: http://127.0.0.1:8118
api_key: <token数字:字符>
allowed_chat_ids:
- 123456
- platform: broadcast
proxy_url: http://127.0.0.1:8118
api_key: <token数字:字符>
allowed_chat_ids:
- 123456
注意这里使用的是http代理,socks5代理貌似有bug
接入语音助手
天猫精灵
Google Assistant
自定义
UI Icons
https://materialdesignicons.com/icon/air-conditioner
usage: mdi:air-conditioner