智能家居实施状况汇总

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”:美的。协议的不同决定了设备会有一些厂商特有的属性,比如美的需要额外的 idkey 用于授权。
  • ip:设备的本地 IP。
  • ui:显示用的设备图标。
  • x:图标 x 坐标
  • y:图标 y 坐标
  • width:图标宽
  • height:图标高
  • properties:设备属性集

属性对象又有如下一些必需的属性:

  • name:属性名称,显示用
  • type:属性值类型,支持 “bool”、”radio”、”range”、”range+”、”text”、”rgb”。
  • id:属性 id。对 miot 类型设备,id 是通过 siidpiid 合成而来的,仅具有 SmartHome 业务之用;但是对 midea 设备,id 值是需要拿来调用其协议库的,不能随意更改。
  • value:属性值。可以不在 devices.json 文件内声明,后端会自动以最新值赋值并传递给前端。

设备高级属性

  • timers:预设一组定时器,在到达指定时间时批量应用指定设备属性值。定时器基于 APScheduler 库实现,采用与其相同的属性描述,从而可以透传定时器参数到 APScheduler 接口。
  • scenes:预设一组场景,选中时批量应用指定设备属性值。

server.py

功能还比较简单,仅有两个 API:

  1. @app.get('/model/init') 获取所有设备当前状态,以 json 格式返回。

  2. @app.post('/') 更新设备属性。

request 消息体格式:

1
2
3
4
5
6
7
{
"ip": ...
"value": ...
"id": ... // for midea
"siid": ... // for miot
"piid": ... // for miot
}

路由函数会借机重新获取所有设备的最新状态并通过 response 通知到前端,效果同 /model/init

这里可能会跟后续的 devices.json 拆分改造一起做下优化,仅返回 request 标识设备的最新状态。至于通过其它终端所做的修改,会通过 websocket 广播到所有终端。

前端

搭配 AntD,实现了三层的组件结构:

<SmartHome /> 唯一,挂在 <App /> 下边。除了负责渲染设备外,SmartHome 还使用 svg 渲染了一个户型图作为背景图。将设备图标显示在户型图的合适位置,就可以“按图索骥”了。

<SmartDevice /> 其实是一个 antd.Modal。当点击某个设备图标时,SmartDevice 会以此设备属性动态渲染并显示。

评论