Blocky Wait based on Item

Hi,

im not sure if, or how this can be achieved.
I would like to replace the remaining Wait condition in the below Blocky Rule to be based on an item (or the variable PumpRunTime).

since im quite new to blocky im stuck a bit and would appreciate any help

Long waits are a bad idea and should only be used rarely.

And the wait block does not support variables.

You should use a timer instead. That lets the rule exit and run the scheduled code in the background.

It looks like what you really need here is a looping timer. There’s a block library on the marketplace that implements a looping timer which can replace this whole while loop and let you use the state of an Item for the delay without tying up this rule for an indeterminate amount of time.

I think the use case is just about a variable timer to switch a pump. This is part of the standard blockly sets and looks like this:

I think there is more going on though because there’s a repeat while loop and a rate limit block in the code above in addition to sending ON, waiting five seconds, then OFF to an Item.

It’s basically a busy wait loop which sometimes does something and would better be implemented with a looping timer.

The 5 seconds can be replaced with the state of an Item, unlike the wait for block which cannot. This also has the advantage of not tying up the thread doing nothing, greatly increasing the chance of a multithreaded access exception.

It’s less awkward using straight JS Scripting though. I had to make certain shortcuts to make the library usable in blockly.

var ohrt = require('openhab_rules_tools');

var loopingTimer = cache.private.get('loopingTimer',  () => ohrt.LoopingTimer());
loopingTimer.loop(() => {
  // command the pump to ON if it's not already ON
  items.ESPHome_pws_Pump_1.sendCommandIfDifferent('ON');
  // If the moisture is less than the threshold repeat the loop in five seconds
  if(items.ESPHome_pws_SoilM_Sens_1.numericState < items.ESPHome_pws_Soil_Moisture_Level_1.numericState) {
    return 'PT5S';
  }
  // no longer too dry, turn off the pump and exit (return null to exit the loop)
  else {
    items.ESPHome_pws_Pump_1.sendCommandIfDifferent('OFF');
    return null;
  }
}, 0, "loopingTimer"); // By setting the initial timeout to 0 the first loop in the timer will run immediately

maybe some more explanation what i want to archive.

  1. comparing 2 number items and if the first one is smaller then the 2. one turn on the pump for a certain time (based also on a number item)
  2. then turn it off and wait some time (again based on a number item) before it will check again.

and yes its for a pump to water a couple of plants.
Everything i tried till now, except my initial post, results in not turning of the pump at all.

That’s exactly what my examples above do. They use a looping timer to do it as a more appropriate way to implement it compared to sleep. And it has the added bonus that you can use the state of an item in place of the 5 use the numeric state of an Item.

my goal was that pump would run, for example 5 seconds then switch off and wait for a certain time again, to allow the water to sattle and then check again.

for example: the pump will run for 5 seconds, turn off and wait for 1 minute before checking again.
The second Wait was till now my problem to implement using a timer or loop.

maybe im thinking to complicated :thinking:

Ok, that is slightly different and I don’t know if the looping timer block can do that. But the JS version can.

The way looping timer library works is it runs a function and then rescheduled based on the return value function. If it returns null the loop stops. Otherwise the return value is when to run the next iteration of the loop.

This let’s you do what you describe pretty easily.

var ohrt = require('openhab_rules_tools');

var loopingTimer = cache.private.get('loopingTimer',  () => ohrt.LoopingTimer());
loopingTimer.loop(() => {

  if(items.ESPHome_pws_SoilM_Sens_1.numericState >= items.ESPHome_pws_Soil_Moisture_Level_1.numericState) {

    items.ESPHome_pws_Pump_1.sendCommand('OFF');
    return null; // end the loop

  }

  else if(items.ESPHome_pws_Pump_1.state == 'ON') {
    
    // command the pump to OFF
    items.ESPHome_pws_Pump_1.sendCommand('OFF');
    return 'PT1M'; // wait for one minute

  }
  else {
 
    // command the pump to ON
    items.ESPHome_pws_Pump_1.sendCommand('ON');
    return 'PT5S'; // wait for five seconds
  }

}, 0, "loopingTimer"); // By setting the initial timeout to 0 the first loop in the timer will run immediately

Unfortunately, I couldn’t figure out a way to support different return value in Blockly like that.

You could implement something like that in Blockly directly but it’s going to be way more complicated than using an online block with the above code, or using JS directly.

Thanks a lot, i think your right doing it then directly in JS is the way to go.
Will look into it.

again thanks for the quick help.