scratch-extension-development icon indicating copy to clipboard operation
scratch-extension-development copied to clipboard

Wait for x seconds

Open pbel78 opened this issue 8 months ago • 1 comments

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

pbel78 avatar Mar 25 '25 13:03 pbel78

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
    }
}

pbel78 avatar Mar 25 '25 15:03 pbel78