在Node中创建长时间运行,可中断功能的策略?

时间:2013-07-22 20:53:30

标签: node.js

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

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

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

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

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

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

这是我的想法的概念,但是operationsSprinkler函数阻塞,因此需要修改或重写。

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");

2 个答案:

答案 0 :(得分:2)

只需使用setTimeout

var timer = setTimeout(stopSprinkler, 15_minutes_in_seconds);

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

答案 1 :(得分:1)

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

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

更换您的operationsSprinkler逻辑将类似于:

/*
 * 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);
}