0%

只靠一个米家门窗传感器搞定浴室自动化

背景

最近心血来潮买了个米家门窗传感器,打算用在浴室实现一种人来灯亮,人走灯灭的效果,但买回来后却发现实际场景比我想象中要复杂得多。为啥呢?门窗传感器最大的问题在于只能感知开/合两种状态,所以无法得知是否有人在浴室内。如果你仅靠闭门来触发关灯的话,就会有一个大问题:当你触发开门的时候灯亮了,然后你走进浴室,这时关门,pa 的一下,灯灭了。。尴尬。。

方案

如果要解决这个问题,首先想到的是再买个人体红外感应器配合来用。但一来吧,总觉得为了这一个小自动化功能买两个传感器不经济;二来红外感应器在浴室的表现并不好(覆盖角度有限制而且有些浴室设计还是分区的,加上浴室水蒸气有时会干扰红外检)因此不是个很好的方案。

但东西都买回来了,总不能丢一边吃灰吧。好在办法总比困难多。门窗传感器本身虽然不足以检测到人,但米家给我们提供了其它逻辑工具啊~

来看看这个问题,其实可以抽象成如何设计一个有限状态机(Finite Automate)以保证浴室自动化符合我们的要求的问题,其中:

要处理的浴室状态有:

  • close_out: 室内无人且门属于关闭状态(此状态时灯与排气扇关闭)
  • open_wait: 室内无人且门属于打开等待进入状态(此状态时灯与排气扇打开)
  • close_in: 室内有人且门属于关闭状态(此状态时灯与排气扇保持打开)
  • open_in: 室内有人且门属于打开状态(此状态时灯与排气扇区保持打开)

tips: 因为还要考虑人是否在内,所以要考虑的状态有四个而非简单的开和闭两个。

影响状态变换的条件有:

  • open: 浴室门打开
  • close: 浴室门关闭

但实际上还有个隐藏条件可以利用:

  • time_elaspe: 时间流逝 ns(比如我们假定现实中 90% 的场景下人进入浴室,都会在 15s 内关上门)

如果把人工干预也算上,那还可以加上:

  • manual: 检测到手动操作(例如,手动关灯)

最终设计出来的状态变换图如下

toilet fa

其中 close_out 即是起始状态也是最终状态。

对应状态转换表如下

open close time elaspe manual
close_out open_wait - - -
open_wait - close_out open_in -
close_in close_out - - close_out
open_in - close_out - -

横杠 - 表示该状态下不接受此输入的意思

验证

接下来我们把要处理的场景跑一遍,看上述 FA 能否满足我们的要求。

为了简化表述,我们把状态和条件均用数字代替:

  • state set: close_out(1), open_wait(2), close_in(3), open_in(4)
  • criteria: open(1), close(2), time_elaspe(3)

toilet fa with numbers

场景一:长时间事务,会关门进行(如洗澡,蹲坑)

输入:1, 2, 1, 2
状态变换过程:1->2->3->4->1

toilet fa scene 1

最终状态为 close_out,可接受,符合预期

子场景 1.1:人在里边临时开门(不超时)

输入:1, 2, 1, 2
状态变换过程:1->2->3->4->1
最终状态为为 close_out,可接受,但不符合预期(预期状态是保持 close_in),需要将输入调整为 1, 2, 1, 2, 1, 2(也就是临时开门后再执行一次开关门,中间会经历一次灯断电,体验稍差)
状态变换过程:1->2->3->4->1->2->3,符合预期

toilet fa scene 1.1

场景二:短时间事务,不关门(如洗手,时间足以触发条件 3)

输入:1, 3, 2
状态变换过程:1->2->4->1

toilet fa scene 2

最终状态为 close_out,可接受,符合预期

场景三:误操作,开门后立马关门(时间不足以触发条件 3)

输入:1, 2
状态变换过程:1->2->3
最终状态为 close_in,非可接受状态,因此要人工介入,使得

输入变为: 1, 2, 4
状态变换过程:1->2->3->1

toilet fa scene 3

最终状态回到 close_out,可接受,符合预期

总结

可以看到在场景 1.1 & 3 下若没有人工介入依然是无法很好地处理的。好在 1&2 占了我们日常场景的 90% 以上,总的来说此方案还是利大于弊。

实现

由于笔者使用的是米家 APP,因此这里仅展示基于米家『场景』模块的实现(理论上只要支持上述触发条件的平台都能实现)

这里的场景指的是米家 APP 上的『场景』模块,与我们文章上述提到的场景并非同一概念
米家场景分为自动(又称作智能)和手动两类,手类执行的场景除了手动操作外,还可以通过自动场景来触发

我们把浴室的状态与米家的场景对应起来(有些状态可能会对应多个场景),得到以下场景

close_out

  • 触发条件:门窗传感器开
  • 执行动作:
    1. 开浴室灯 & 排气扇(这块可以根据实际需求自行调整)
    2. 关闭智能 close_out
    3. 开启智能 open_wait
    4. 关闭智能 open_in
    5. 执行手动场景 open_wait.time_elaspe

tips: 其中命名 close_out 代表该米家场景打开时我们的浴室是处在状态 close_out 的,一旦检测到门窗传感器打开将执行相应动作。动作 2&3 组合起来实现了状态切换的效果(关闭当前智能,打开目标状态对应的智能,也就是 open_in);动作 5 是模拟以时间条件为输入的效果,详见 open_wait.time_elaspe 的配置
此外,这里还出现了一个看似没啥用的动作 关闭 open_in,将在后面作解答

open_wait.time_elaspe

  • 触发条件:手动触发
  • 执行动作:
    1. 延时 15s(时间可以自行调整成符合家庭习惯的数值)
    2. 开启 open_in

open_wait

  • 触发条件:门窗传感器关
  • 执行动作:
    1. 关闭智能 open_wait
    2. 开启智能 close_in
    3. 开启智能 close_in.manual
    4. 关闭智能 open_in

tips: 这里的状态切换是由动作 1&2&3 共同组成的,这是因为在我们的状态转换表里面 close_in 状态是可以被条件 open / manual 任其一触发转换到其它状态,所以状态 close_in 其实是对应了两个米家智能,这两个智能只能是同时开启同时关闭,才能保证自动化不会出现混乱

close_in

  • 触发条件:门窗传感器开
  • 执行动作:
    1. 关闭智能 close_in
    2. 关闭智能 close_in.manual
    3. 开启智能 open_in

close_in.manual

  • 触发条件:浴室灯 or 排气扇任一关闭(这块可以根据实际需求自行调整)
  • 执行动作:
    1. 关浴室灯 & 排气扇(这块可以根据实际需求自行调整)
    2. 关闭智能 close_in
    3. 关闭智能 close_in.manual
    4. 开启智能 close_out
    5. 关闭智能 open_in

open_in

  • 触发条件:门窗传感器关
  • 执行动作:
    1. 关浴室灯 & 排气扇(这块可以根据实际需求自行调整)
    2. 关闭智能 open_in
    3. 开启智能 close_out

最后,还记得上面提到的 关闭 open_in 这个看似没啥用的动作吗,其实不仅在 close_out 状态中,在除 open_in 外的每一个状态动作执行时都要加上这个动作。这是因为利用米家 APP 的延时模拟时间条件的输入这个是无法取消的,即是说一旦执行了 open_wait.time_elaspe,15s 后必定会打开 open_in 场景,而这时我们的浴室可能处在任何一个状态。为了避免因此导致的混乱,我们才需要在每个状态的动作加入此动作

tips: 超时效果也可以通过门窗传感器自带的超时未关通知能力来实现,这样就相当于是可中断的,不需要上述的的补偿操作了。但有个问题是,目前我这款传感器好像只支持配置分钟时间粒度

手机截图如下

toilet fa scene 1

结语

以上配置对于普通用户(尤其是没有编程基础的)来说还是有些过于复杂了,建议厂家可以将状态机直接集成到门窗传感器中的,用户只要决定用或不用即可。

另外,米家平台提供的基础能力也比较有限(可能是基于易用性及安全性的考虑?),导致很多效果实现起来还是比较困难。不管怎样,希望希望米家能加入一些变量能力,可以通过动作来设置变量值,也可以根据变量值的不同来触发不同的智能,这样会有更高的可玩性。