我正在为树莓派上带有Node的机器构建一个控制系统。如果其中一个安全继电器断开,则某些过程需要立即停止。因此,我需要每隔100ms id检查一次安全继电器是否打开,如果打开,则发送信号以停止运行某些功能。
通常,如果Relays.allClosed
为假,将需要停止几个功能。
var Relays = {
relay1: false,
relay2: false,
allClosed: false,
checkRelays: function() {
if (this.relay1 == true && this.relay2 == true) {
this.allClosed = true
} else {
this.allClosed = false
console.warn("relay open")
}
}
}
var safetyCheck = function() { //checks if safety relays are all closed every 100 ms
setInterval(function() {
Relays.checkRelays()
}, 100)
}
safetyCheck()
Machine.run = function(distance) {
if (Relays.allClosed) { //checks before running the process if the relays are all closed for safety
// if at any point while running this Relays.allClosed becomes false, function needs to stop running
setTimeout(function() {
console.log('advancing press');
i++;
if (i < distance) {
pressLoop();
}
}, 1000)
} else {
console.log("can't run machine because one or more safety relay is open")
}
}
答案 0 :(得分:0)
当发生有意义的事情时,您应该使用EventEmitter
之类的东西来发出事件。这可能是您的allClosed
值的状态变化(尽管我认为您不断轮询变化的中继状态的方法是一种反模式,并且应该始终使用基于事件的逻辑)。 / p>
但是在任何情况下,假设引发allClosed
事件,您都可以捕获该事件并停止运行的代码:
Machine.run = function(distance) {
if (Relays.allClosed) { //checks before running the process if the relays are all closed for safety
// if at any point while running this Relays.allClosed becomes false, function needs to stop running
let timer = setTimeout(function() {
console.log('advancing press');
i++;
if (i < distance) {
pressLoop();
}
}, 1000);
myEventEmitter.on("allClosed", () => {
clearTimeout(timer);
})
} else {
console.log("can't run machine because one or more safety relay is open")
}
}
此操作将在下一次迭代时取消,但是如果pressLoop
以某种方式长时间运行,则也应准备中途停止该操作。
以下代码说明了(用按钮代替物理继电器)如何运行整个事件一系列事件。
// just jQuery for mockup - ignore
$('.relay').on("click", function () {
$(this).toggleClass("open").toggleClass("closed");
events.emit("relayChanged", {id:$(this).data("id"), isClosed: $(this).is(".closed")})
})
function RelayMonitor(){
var relaysClosed = {
"1": true,
"2": true
}
this.init = function(events){
events.on("relayChanged", (args) => {
relaysClosed[args.id] = args.isClosed;
if(Object.values(relaysClosed).every(x => x)) {
events.emit("allClosed");
}
});
}
}
//const EventEmitter = require('events'); // included as cdn import here
var events = new EventEmitter();
events.on("allClosed", () => console.log("all relays closed"));
var monitor = new RelayMonitor()
monitor.init(events);
.closed {
background-color:green
}
.open {
background-color:red
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/EventEmitter/5.2.5/EventEmitter.js"></script>
<button data-id="1" class="relay closed">Relay1</button>
<button data-id="2" class="relay closed">Relay2</button>
答案 1 :(得分:0)
您应该改用基于事件的结构,例如:
const EventEmitter = require('events');
const input = new EventEmitter();
通过这种方式,您可以发出以下事件:
relay1.watch((err, value) => input.emit("relay1", !!value));
这样,您可以在多个位置将回调附加到中继:
input.on("relay1", on => console.log(on));
现在,当所有中继都在其上时,就可以轻松获得另一个事件:
let relaysCount = 0;
function updateCount(on) {
if(on) {
relaysCount++;
if(relaysCount === 2)
input.emit("allOn");
} else {
relaysCount--;
input.emit("someOff");
}
}
input.on("relay1", updateCount);
input.on("relay2", updateCount);
现在,像您的示例一样,在开始超时时,如果某些设置为“关闭”,则可以轻松取消该操作:
input.on("allOn", () => {
const task = setTimeout(/* sth */, 1000);
input.on("someOff", () => clearTimeout(task));
});