0

我希望在 Node 中创建一个服务器,该服务器将在我的 Raspberry Pi 上运行以处理更改的 GPIO 引脚。(我是 Node 新手,但很高兴能学习新东西)

这些引脚使用 OpenSprinkler 硬件控制洒水阀继电器,一次只能打开一个阀门。硬件不允许您查询阀门状态,因此需要在软件中处理。

当网络请求进入时,类似于“操作站 1 15 分钟”,我需要能够完成该命令并等待适当的分钟数,然后再将引脚设置回关闭。每次执行都应该能够自行停止,我不想依靠外部命令来关水,以免软件故障将我的院子变成池塘。

如果第二个命令在第一个命令运行时到达,我希望第一个操作自行终止,然后允许第二个命令运行。此终止将提前停止操作,记录它运行了多少分钟等。

我已经在 Python 中使用线程和队列编写了这个,但我希望看看它是否可以在 Node.js 中更干净地完成。

我很好奇我是否应该查看线程、生成子进程或其他东西来实现我正在寻找的东西?我需要某种非阻塞、长时间运行的执行,可以监听要中断的信号。

这是我的想法的一个概念,但是操作Sprinkler 功能阻塞,因此需要对其进行修改或重新编写。

net = require('net');

function operateSprinkler(minutes, station) {

    console.log('Operating Station ' + station + ' for ' + minutes + ' minutes.');

    var ms = minutes * 60 * 1000;
    var endTime = (new Date().getTime()) + ms;

    // Manipulate gpio pin to turn on sprinkler (pseudo-code here)
    gpio.on()

    while(new Date().getTime() < futureTime) {
        // Hang out until time expires
        // Listen for a signal that interrupts this function
    }
    else {
        gpio.off() // pseudo-code
    }

    console.log('Finished operating station.');
}

net.createServer(function(socket) {

    socket.on('data', function(data) {
        try {            
            var json = JSON.parse(data);
            // Make sure "minutes" and "station" were passed
            if (json.hasOwnProperty('minutes') && json.hasOwnProperty('station')) {
                operateSprinkler(json['minutes'], json['station']);
            }
        }
        catch(e) {
            console.log('Error. Invalid command.');            
        }
        socket.end();
    });

}).listen(5000);

console.log("Server running at port 5000\n");
4

2 回答 2

2

只需使用setTimeout.

var timer = setTimeout(stopSprinkler, 15_minutes_in_seconds);

您可以将此计时器存储到一个变量中,如果/当另一个命令进入时,只需检查该变量是否已设置。如果已设置,您可以使用clearTimeout停止计时器并手动处理停止洒水器。

于 2013-07-22T20:59:00.913 回答
1

通常,您需要重新编写代码以处理事件,无论是来自计时器还是来自喷水器控制器。

在您提供的示例中,使用 setTimeout,存储返回的 timeoutId、洒水站和您需要访问的任何其他数据,以便您以后可以取消它。

替换您的操作Sprinkler 逻辑将如下所示:

/*
 * current station is false if not running
 *
 * or {
 *     station:   stationid,
 *     duration:  time,
 *     start:     Date.now(),
 *     timeoutId: timeoutId
 * }
 */
var currentStation = false;

function operateSprinkler(minutes, station) {

    if(currentStation) {
        console.log('Cancelling station: ' + currentStation.station);

        gpio.off(); // Will need some way to look up by station...

        clearTimeout(currentStation.timeoutId);
    }

    var ms = minutes * 60 * 1000;
    var endTime = (new Date().getTime()) + ms;

    currentStation = {
        station: station,
        duration: ms,
        start: Date.now();
    };

    console.log('Operating Station ' + station + ' for ' + minutes + ' minutes.');

    // Manipulate gpio pin to turn on sprinkler (pseudo-code here)
    gpio.on()

    currentStation.timeoutId = setTimeout(function() {
        gpio.off();
        currentStation = false;

        console.log('Stopping station ' + currentStation.stationid);
        console.log('Finished operating station.');
    }, ms);
}
于 2013-07-22T21:15:54.130 回答