我希望在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");
答案 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);
}