始终打开/定时/关闭灯的可靠计时器

物联网 智能家居 domoticz
2021-06-03 03:16:48

我有一个 ZWave 灯泡和一个 ZWave 4 按钮墙壁开关,它们都连接到安装在 Raspberry Pi 上的 Domoticz。

我想要以下场景:

  • 按钮 1:灯亮 30 分钟
  • 按钮 2 : 灯灭
  • 按钮 3:灯常亮
  • 按钮4:召唤克苏鲁

每个按钮都会覆盖上一个操作(按钮 3 -> 按钮 1 = 打开 30 分钟)

按钮的接线和编程很容易,但现在定时器呢?我想避免创建自制服务,因为我害怕弄乱init.d.

我有 3 种可能性:


Domoticz 虚拟开关

Domoticz 允许创建一个虚拟开关,它可以在界面中给定的一段时间后改变状态:

domoticz 虚拟开关

优点

  • 现成的计时器!
  • 我可以在墙壁开关和灯之间快速交互

缺点

  • 虽然 Domoticz 处理 MQTT,但会有很多 LUA 脚本和“块状”来互连设备
  • 时间可能不容易配置......

atatq

at 是一个 linux 命令,用于及时计划一个动作,就像

at [when] < [what]

优点

  • 多定时器服务
  • 易于使用和调用

缺点

  • at 只给出一个唯一的 ID,除非解析计划的命令,否则我无法为作业命名(除非使用魔术 linux 命令......)
  • 因此我需要使用数据库编码/实现一个作业匹配器

定时任务表

crontab 是一个用于计划重复性任务的 linux 服务。就我而言,这将是一个简单的

# check every minute
* * * * * /path/checktimer.sh

优点

  • 可靠的时间触发

缺点

  • 无法管理秒...
  • 仍然被迫在某处维持一个工作匹配器

我的问题:

  • 您是否必须像这样管理计时器?
  • 我是否错过了其他更可靠/可配置的解决方案?
  • 您对上述解决方案有偏好吗?
3个回答

根据请求,我将尝试举例说明如何解决它(使用 bash shelljobs处理):

按钮 1:
当打开灯 X 30 秒和灯 Y 5 分钟时:

echo "Switch on lamp_x" && sleep 30s && echo "Switch off lamp_x" &
echo "Switch on lamp_y" && sleep 5m && echo "Switch off lamp_y" &

由于过程限制,这必须在两个单独的行上,显然应该用实际命令替换上面的 echo。

按钮 3:
然后您可以kill通过获取工作 pid 并杀死它睡眠以停止它并保持灯亮:

kill $(jobs -p %?lamp_y)
echo "Switch on lamp_y"

命令链接的事实&&将阻止命令sleep运行,因为睡眠没有正确退出。
这不会处理不存在的工作,这可能会导致 kill 返回错误,这里应该不会发生任何不好的事情。

按钮 2:使用与按钮 3 相同的方法,但使用停止命令并杀死作业(如果有)。

按钮 4:

echo "Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn"

(对不起,我不知道你在这里想要什么,为了完整性而设置)


关于实现的细节jobs

jobs -p %?lamp_y返回与-pjobspec 匹配的作业的当前 pid %?lamp_y这意味着lamp_y可能出现在命令行中的任何位置,仔细选择此处使用的内容(但我敢打赌,您对要控制的事物或事物组有一个唯一标识符)。

如果你想为此使用在线服务,你应该可以使用https://www.stringify.com它们支持序列和变量(和定时器)。我没有生气地使用他们的服务,但看起来您应该能够使用计时器来减少变量(它确定剩余时间),并且各种触发事件可以强制变量为新值。

它们支持 IFTTT 集成,因此几乎可以以某种方式链接任何端点。

我发现了另一种非常昂贵但使用外部进程的方法,例如 PHP 的system: screen

首先,安装它:

sudo apt-get install screen

然后调用你的函数

screen -dm -S taskid bash -c 'sleep 20 && command'
    -dm : detach process
    -S  : identify screen by name

列出您的任务

ls /var/run/screen/S-www-data (or S-anotheruser, warning it is user bound, or sudo it)

杀死它

screen -S taskid -X kill
    -S : identify screen by name
    -X : access the screen and perform this command