智能家居实施状况汇总
12 月 11 号那天把宽带移到了新家,终于可以将我的智能家居想法正式实施了。
网络布线
弱电箱在玄关鞋柜里边,我把电信光猫改了桥接直接放弱电箱里了。中海预先布了 5 条线,两条六类,三条超五类,都可以支持千兆,省了从弱电箱到客厅重新布线的麻烦。
但是书房居然没有布线。这就很麻烦,因为我的台式机、NAS 等一些常用的有线设备肯定要放书房的啊。300M 的宽带从客厅跨过三道墙进入书房后,实测无线网的网速只剩下将将 100M 了。拿另一台路由器做无线 Mesh,发现不管放哪儿,网速甚至都提不到 200M。
无奈还是要做有线 Mesh,另一台路由器直接放到了书房里。网线就扔地上,经过的走廊说服了我老婆铺上地毯。网线是那种扁平的,恰好以这种温馨的家居设计遮盖了丑陋的外露网线,还不影响走动。
有了书房的路由做中继,实测在主卧的 WIFI 网速也有 200M 了,完全满足偶尔在床上看看电影的需求。
智能设备选购
市场越来越大,也越来越乱了。除了米家、涂鸦、天猫精灵、欧瑞博这几个开放型的智能平台,现在是个电器生产厂家都在做自己的智能家居平台了,什么海尔格力美的华为。百花齐放对智能家居产业当然是好事,说明大家对此领域的广阔前景有共同的认知。
但是太缺少标准化的规范了。且不说 WIFI、蓝牙、Zigbee 这种争论已久的网络传输层面上的分歧,只关注 WIFI 实现的话,其市场乱象也已经到了人所不能忍的地步了。生产厂家仿佛看到了新的护城河,纷纷实现各不相容的数据结构跟协议。又有何用呢?“智能”两字只是对已有硬件功能的延展,并没有催生出突破性的新功能。假如全行业采取统一规范的数据结构和协议,反而能让生产厂家们更聚焦于硬件能力的提升。
唉,瞎啰嗦了几句。但是现状已经支离破碎,只有去适应了。
所以大原则还是我之前的思路,小米系和 HA 系。使用量够大,且是开放甚至是开源的方案,经过社区验证过,实施起来能节省很多时间。
截止目前,选购了如下智能单品:
- 绿米 A1 电动窗帘轨道电机 x 3,双十一总价 1584.15。
- 小米米家鎏金版空调2匹挂机 x 1,2999。
- 美的 酷金/大1匹变频空调冷暖家用挂机智能空调 x 3,双十一总价约 6300。
可惜中海免费送了一套西顿的灯具,惹得我老婆不同意换掉这些便宜货。所以灯光相关的智能化场景只能等以后再说了。
SmartHome
SmartHome 是我自己设计的一套 B/S 结构的智能家居控制系统。灵感来自于 HomeAssistant,HA 是一个开源的家居自动化解决方案,其 puts local control and privacy first 的理念我深感赞同。所以,SmartHome 也同 HA 一样,仅支持部署在设备所在局域网内。我现在用的是一块树莓派 3B 做主机,稳定性良好,暂时没有发现问题。
如图,SmartHome 前端采用 React.js 框架实现,后端通过 Sanic.py 框架实现,设备配置存储在 devices.json 文件里。
devices.json
偷懒把所有设备描述都塞到了一个文件里(前期开发聚焦在前后端的开发上),形成了一个 devices
数组,数组中的一个对象即是一个设备。
设备必需属性
name
:设备名称,可以显示到前端界面上。protocol
:设备所用协议,现在仅支持 “miot”:小米,”midea”:美的。协议的不同决定了设备会有一些厂商特有的属性,比如美的需要额外的id
和key
用于授权。ip
:设备的本地 IP。ui
:显示用的设备图标。x
:图标 x 坐标y
:图标 y 坐标width
:图标宽height
:图标高properties
:设备属性集
属性对象又有如下一些必需的属性:
name
:属性名称,显示用type
:属性值类型,支持 “bool”、”radio”、”range”、”range+”、”text”、”rgb”。id
:属性 id。对 miot 类型设备,id
是通过siid
和piid
合成而来的,仅具有 SmartHome 业务之用;但是对 midea 设备,id
值是需要拿来调用其协议库的,不能随意更改。value
:属性值。可以不在 devices.json 文件内声明,后端会自动以最新值赋值并传递给前端。
设备高级属性
timers
:预设一组定时器,在到达指定时间时批量应用指定设备属性值。定时器基于 APScheduler 库实现,采用与其相同的属性描述,从而可以透传定时器参数到 APScheduler 接口。scenes
:预设一组场景,选中时批量应用指定设备属性值。
server.py
功能还比较简单,仅有两个 API:
@app.get('/model/init')
获取所有设备当前状态,以 json 格式返回。@app.post('/')
更新设备属性。
request 消息体格式:
1 | { |
路由函数会借机重新获取所有设备的最新状态并通过 response 通知到前端,效果同 /model/init
。
这里可能会跟后续的 devices.json 拆分改造一起做下优化,仅返回 request 标识设备的最新状态。至于通过其它终端所做的修改,会通过 websocket 广播到所有终端。
前端
搭配 AntD,实现了三层的组件结构:
<SmartHome />
唯一,挂在 <App />
下边。除了负责渲染设备外,SmartHome
还使用 svg 渲染了一个户型图作为背景图。将设备图标显示在户型图的合适位置,就可以“按图索骥”了。
<SmartDevice />
其实是一个 antd.Modal。当点击某个设备图标时,SmartDevice
会以此设备属性动态渲染并显示。