scratch-extension-development
scratch-extension-development copied to clipboard
Wait for x seconds
Hi
I solved a lot of things for the MQTT integration to control lights here: https://github.com/pbel78/scratch2/
I want to add to my code a delay if a turnLightOn function is called with a transition time of 2 seconds I want the block to wait for 2 seconds before the next block is executed. Somehow all ideas I had to realize this didn't resulted in the expected functionallity. Did I miss any documentation how to wait correctly (i.e. the same way as if I would drag in a "wait X seconds" block from the control section.
Can I somehow refer the original block in my code?
What I tried: In Javascript
- to do an async function call with a promise that is waiting
- try to do a loop check for the time passed
In Scratch:
- A custom block combining my own block with the original wait block => this worked but I loose the functionallity of the dropdown list for the lamp fixtures which I have in my new functions.
Example for the light brightness which did not work :) :
setLightBrightness({ LAMP,BRIGHTNESS,TRANSITION }) {
if (this.client) {
this.mqttSend({ MESSAGE, TOPIC })
const TOPIC = 'zigbee2mqtt/'.concat(LAMP).concat('/set');
const MESSAGE = this.addTransition(BRIGHTNESS, TRANSITION);
this.mqttSend({ MESSAGE, TOPIC })
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > Number(TRANSITION) * 1000 ){
break;
}
}
return 'helloWorld'
}
}
Thank you for any hint. Regards Petr
Ok. Sorry for answering my own questions but I guess somebody else might need that one as well:
you can use util.yield. That is a Scratch function which keeps the control for one more "frame". And it looks to me the opcode is reexecuted again and again until the yield is not called anymore and control is passed to the next bloc.
I tought it didn't worked as I tested my block only by double clicking the block and checking when the next block started. But if the green flag is not clicked it looks to me like there are no frames. Which means the next block was never reached. here the code that works for me:
setLightBrightness(args, util) {
const { LAMP, BRIGHTNESS } = args;
const TRANSITION = Number(args.TRANSITION);
if (this.client) {
// First-time init
if (!util.stackFrame.sentMessage) {
const TOPIC = 'zigbee2mqtt/'.concat(LAMP).concat('/set');
const MESSAGE = this.addTransition(BRIGHTNESS, TRANSITION);
this.mqttSend({ MESSAGE, TOPIC });
util.stackFrame.sentMessage = true; // mark as sent
}
// Handle wait
const durationMs = Math.max(0, TRANSITION * 1000);
if (util.stackTimerNeedsInit()) {
util.startStackTimer(durationMs);
util.yield();
} else if (!util.stackTimerFinished()) {
util.yield();
}
// After wait is complete, execution will resume here
}
}