3

我有一个长时间运行的 python 进程在树莓派(控制花园)上无头运行,如下所示:

from time import sleep

def run_garden():
    while 1:
        /* do work */
        sleep(60)

if __name__ == "__main__":
    run_garden()

60 秒的睡眠时间足以让我的花园发生任何变化(湿度、空气温度、打开泵、关闭风扇等),但是如果我想手动覆盖这些东西怎么办?

目前,在我的/* do work */循环中,我首先调用另一台保存配置变量的服务器,我可以通过 Web 控制台更新这些配置变量,但它缺乏任何实时感,因为它依赖于 60 秒循环(例如,您可能会更新 Web 控制台,然后等待 45 秒以使所需的效果生效)

树莓派运行run_garden()专用于花园,它基本上是唯一占用资源的东西。所以我知道我有空间做某事,我只是不知道是什么。

一旦循环发现配置变量已更新的事实,循环就可以进行指数退避以继续检查交互,而不是等待 60 秒,但感觉并没有好很多。

有没有更好的方法可以基本上进入这个长期运行的过程?

4

3 回答 3

1

为什么不使用基于事件的循环而不是休眠一段时间。

这样,您的循环将仅在检测到更改时运行,并且始终在检测到更改时运行(这是您问题的重点?)。

你可以通过使用来做这样的事情:
python 事件对象

只需等待一个或所有事件对象被触发并运行循环。您也可以等待 X 事件完成,等等,这取决于您是否期望一个变量会更新很多。

甚至像这样的系统: 广播事件

于 2013-03-24T13:25:49.493 回答
1

监听主循环中的套接字。在套接字读取调用上使用超时(例如 60 秒,应该执行下一次花园更新的时间),以便在没有命令进入时至少每分钟恢复正常功能。

如果您需要花园式更新的速度不快于每分钟,您需要检查自上次更新以来的时间,因为当有命令进入时,读取调用将大大加快完成

于 2013-03-24T13:34:57.187 回答
1

Python 的select模块听起来可能会有所帮助。

如果您曾经使用过 unix 模拟(例如可能在套接字编程中?),那么它会很熟悉。

如果没有,这里是select我经常推荐的 C 套接字参考部分。这是一个看起来不错的模块文章

警告:第一个参考资料专门针对 C,而不是 Python,但select系统调用的概念是相同的,因此讨论可能会有所帮助。

基本上,它允许你告诉它你感兴趣的事件(例如,套接字数据到达、键盘事件),它会永远阻塞,或者直到你指定的超时时间过去。

如果您使用的是套接字,那么将套接字和标准输入添加到您感兴趣的事件列表中很容易。如果您只是在寻找一种“有条件地睡眠”60 秒的方法,除非/直到检测到按键,那么这也可以。

编辑

解决此问题的另一种方法是让您的 raspberry-pi 在运行 Web 控制台的服务器上“注册”。这可能涉及一些额外的工作,但它会给你你正在寻找的实时效果。

基本上,树莓派通过向服务器发出警报来“注册”自己,然后服务器存储设备的地址。如果使用 TCP,您可以保持连接打开(如果您有防火墙要处理,这可能很重要)。如果使用UDP,可以在注册前绑定设备上的端口,让服务器响应“公告”的源地址。

一旦宣布,当配置。服务器上的选项发生变化,通常会发生以下两种情况之一:

A)您向设备发送一个微小的“ping”(一般意义上,不是 ICMP 主机检测协议),提醒它配置选项已更改。此时主机将立即请求完整配置。设置,获取更新。

B)您发送更新的配置。选项(或者可能是整个配置集)返回到设备。这会减少设备和服务器之间的消息数量,但可能需要更多的工作,因为这似乎与您当前的设置有更大的偏差。

于 2013-03-24T13:44:41.590 回答