(Although what I'm trying to achieve can be done with core nodes, the reason I'd like to do this is to further my understanding of Javascript and Node-RED in general.)
I have written this little sleep dimmer function (link to other forum post), but I'd like to implement some kind of msg.reset to cancel the sleep dimmer.
Is there a way I can interact with the original "thread" or instance, to stop it, when the function itself receives a value in msg.reset?
(If you can correct any of my assumptions or wrong ideas about this, I'd be grateful too)
Assuming this msg.reset is being passed into the same node... then yes - you need to save the instance of the timeout context.foo = setTimeout(.... then it will be available so you can call clearTimeout(context.foo).
Of course this will mean you can only have one running at a time... so you may need to think how to handle that if another msg arrives to trigger another timeout... do you ignore it ? or cancel existing and restart ? or... up to you.
Thanks @dceejay. I'll go with one running at a time - I'd like to use the node status and I guess it would be impossible to show the status of multiple instances!
Do you mean I should save a value into context to indicate that a given fadeout is running? Then look it up and clear the timeout? Or are you talking about storing the function itself in context? Can you give me a pointer as to how I might do that?
well yes that is "more correct" and would allow you to persist the object... but in this case I don't think persistence would be required so I think it's simper to understand.
I don't think I have a problem with the logic of testing for msg.reset, and knowing how to deal with different scenarios (e.g. discard, reset timer and start counting, etc.) but I am really struggling with how to clear the timeout.
I understand that I need to save the function into memory. I have chosen to save to global whilst I figure this out (just for my own testing and understanding, as this means I can use context explorer to see it, and also access it from another node to e.g. test clearing the timeout from another function).
My main function has a function within it, in order to be able to have 2 delays (initial delay, and repeating delay for each fading step).
I have set the outer function (the initial delay) to memory.
When I start the timer, I can use context explorer and I see "[Object Object]"
However when I load this back into memory from another function node, then clearTimeout, the fader just keeps going.
To make it clearer, here's my code (yes, I know I used "id", just ignore the name for now):
FADER FUNCTION
var id = setTimeout(function(){
var i = startval;
function f() {
if (i>0) {
i--;
msg.payload = i;
node.send(msg);
var fadetxt = "Fading " + (i*steptime/1000).toString() + "s, " + i.toString() + "/" + startval.toString();
node.status({fill:"green", shape:"ring", text:fadetxt});
} else {
node.status({});
return;
}
setTimeout( f, steptime );
}
f();
},initialdelay)
global.set('id',id);
And then...
TIMER CLEAR FUNCTION (different node, which I can inject message to for testing)
var id = global.get('id');
clearTimeout(id);
When I inject a message into this second function, it carries on counting
don't use global. It would mean you can only have one instance of your node (as they would all try to use the same global variable)... use a local context one instead.