Help with a rule with multiple timers and if statements

Here’s the rule that I’m trying to get working without much luck. and here’s the logs. The rule triggers and straight away it turns the rule running switch on then off. it isn’t triggering scene 0 even though the state of Inverter_1_Grid is 200ish any ideas?

rule "Auto Solar Power Usage scenes"

when
	Item Inverter_Generation_Combined changed or
	Item Inverter_1_Grid changed
	then
			logInfo("Auto Solar Power Usage scene", "Rule triggered")
	if		(Auto_Solar_Power_Usage_scenes_Running.state == OFF)
				{
		Auto_Solar_Power_Usage_scenes_Running.sendCommand(ON)
			logInfo("Auto Solar Power Usage scene", "Rule running switch on")
		createTimer(now.plusSeconds(5), [ |
		
		if		(Inverter_1_Grid.state > 1000)
				{
			logInfo("Auto Solar Power Usage scene", "scene 0")
		Auto_Solar_Power_Usage.sendCommand(0)
		
		if		(Inverter_1_Grid.state < -2500)
				{
			logInfo("Auto Solar Power Usage scene", "scene 1")
		Auto_Solar_Power_Usage.sendCommand(1)
		createTimer(now.plusSeconds(30), [ |
		

		if		(Inverter_1_Grid.state < -3000)
				{
			logInfo("Auto Solar Power Usage scene", "scene 2")
		Auto_Solar_Power_Usage.sendCommand(2)
		createTimer(now.plusSeconds(300), [ |
		

		if		(Inverter_1_Grid.state < -4500)
				{
			logInfo("Auto Solar Power Usage scene", "scene 3")
		Auto_Solar_Power_Usage.sendCommand(3)
		createTimer(now.plusSeconds(30), [ |

	]) }
	]) }
	]) }
	}  ]) 
			logInfo("Auto Solar Power Usage scene", "Rule running switch off")
	Auto_Solar_Power_Usage_scenes_Running.sendCommand(OFF)
	}
end

2021-06-18 11:07:15.135 [INFO ] [.script.Auto Solar Power Usage scene] - Rule triggered
2021-06-18 11:07:15.139 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch on
2021-06-18 11:07:15.144 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch off
2021-06-18 11:07:16.726 [INFO ] [.script.Auto Solar Power Usage scene] - Rule triggered
2021-06-18 11:07:16.730 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch on
2021-06-18 11:07:16.735 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch off
2021-06-18 11:07:16.769 [INFO ] [.script.Auto Solar Power Usage scene] - Rule triggered
2021-06-18 11:07:16.776 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch on
2021-06-18 11:07:16.782 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch off
2021-06-18 11:07:29.731 [INFO ] [.script.Auto Solar Power Usage scene] - Rule triggered
2021-06-18 11:07:29.734 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch on
2021-06-18 11:07:29.742 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch off
2021-06-18 11:07:31.184 [INFO ] [.script.Auto Solar Power Usage scene] - Rule triggered
2021-06-18 11:07:31.194 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch on
2021-06-18 11:07:31.205 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch off
2021-06-18 11:07:31.210 [INFO ] [.script.Auto Solar Power Usage scene] - Rule triggered
2021-06-18 11:07:43.720 [INFO ] [.script.Auto Solar Power Usage scene] - Rule triggered
2021-06-18 11:07:43.723 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch on
2021-06-18 11:07:43.729 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch off
2021-06-18 11:07:45.135 [INFO ] [.script.Auto Solar Power Usage scene] - Rule triggered
2021-06-18 11:07:45.139 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch on
2021-06-18 11:07:45.153 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch off
2021-06-18 11:07:45.165 [INFO ] [.script.Auto Solar Power Usage scene] - Rule triggered
2021-06-18 11:07:57.799 [INFO ] [.script.Auto Solar Power Usage scene] - Rule triggered
2021-06-18 11:07:57.803 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch on
2021-06-18 11:07:57.807 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch off
2021-06-18 11:07:59.349 [INFO ] [.script.Auto Solar Power Usage scene] - Rule triggered
2021-06-18 11:07:59.353 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch on
2021-06-18 11:07:59.357 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch off
2021-06-18 11:07:59.362 [INFO ] [.script.Auto Solar Power Usage scene] - Rule triggered
2021-06-18 11:07:59.366 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch on
2021-06-18 11:07:59.370 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch off

Yes, that’s what you asked it to do.
Command the switch on (and log it)
Create a Timer, for future execution.
Command the switch off (and log it).
That’s all over in a few milliseconds.

Your Timer should run around five seconds after that, but may well not produce any messages.

You’ll probably want to review how Timers work; it boils down to working like an alarm clock, set it and forget it. An independent job is scheduled for future execution, and the creating rule carries on immediately.

Try this

logInfo("test", "Going to create a Timer")
createTimer(now.plusSeconds(10), [ |
   logInfo("test", "First Timer running, going to create a second Timer")
   createTimer(now.plusSeconds(10), [ |
       logInfo("test", "Second Timer is running")
   ])
   logInfo("test", "First Timer has created Second Timer")
])
logInfo("test", "Rule has created First Timer")

Why not log out the state just before the if(), find out what it really is at that moment?
Beware Units of measurement, and comparing apples with oranges.

Thanks fr the help, here’s the logs showing the state.

it doesn’t look like the if conditions with Inverter_1_Grid are working.

2021-06-18 14:46:28.428 [INFO ] [.script.Auto Solar Power Usage scene] - Inverter_1_Grid -2639.65
2021-06-18 14:46:28.430 [INFO ] [.script.Auto Solar Power Usage scene] - Rule triggered
2021-06-18 14:46:28.434 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch on
2021-06-18 14:46:28.438 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch off
2021-06-18 14:46:28.441 [INFO ] [.script.Auto Solar Power Usage scene] - Inverter_1_Grid -2639.65
2021-06-18 14:46:28.443 [INFO ] [.script.Auto Solar Power Usage scene] - Rule triggered
2021-06-18 14:46:28.447 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch on
2021-06-18 14:46:28.451 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch off
2021-06-18 14:46:41.359 [INFO ] [.script.Auto Solar Power Usage scene] - Inverter_1_Grid -2639.65
2021-06-18 14:46:41.364 [INFO ] [.script.Auto Solar Power Usage scene] - Rule triggered
2021-06-18 14:46:41.367 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch on
2021-06-18 14:46:41.371 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch off
2021-06-18 14:46:42.901 [INFO ] [.script.Auto Solar Power Usage scene] - Inverter_1_Grid -2687.71
2021-06-18 14:46:42.903 [INFO ] [.script.Auto Solar Power Usage scene] - Rule triggered
2021-06-18 14:46:42.907 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch on
2021-06-18 14:46:42.910 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch off
2021-06-18 14:46:42.915 [INFO ] [.script.Auto Solar Power Usage scene] - Inverter_1_Grid -2687.71
2021-06-18 14:46:42.917 [INFO ] [.script.Auto Solar Power Usage scene] - Rule triggered
2021-06-18 14:46:42.920 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch on
2021-06-18 14:46:42.923 [INFO ] [.script.Auto Solar Power Usage scene] - Rule running switch off

The second if-statenment here is nested within the first, so it will only run if Inverter_1_Grid.state > 1000 and Inverter_1_Grid.state < -2500 are both true, which of course will never happen. I believe you want to close the first if-statenment before the second:

		if		(Inverter_1_Grid.state > 1000)
				{
			logInfo("Auto Solar Power Usage scene", "scene 0")
		Auto_Solar_Power_Usage.sendCommand(0)
		}
		if		(Inverter_1_Grid.state < -2500)
				{
			logInfo("Auto Solar Power Usage scene", "scene 1")
		Auto_Solar_Power_Usage.sendCommand(1)
		createTimer(now.plusSeconds(30), [ |

Edit: You might want to look into where you close your other statements as well, even if the if (Inverter_1_Grid.state < -2500) it creates a timer, in that timer it checks if the state is now < -3000 and if true schedules a second timer. This timer in turn checks if the state again has changed, this time to < -4500, and if true schedules a third timer which doesn’t do anything at all.

Perhaps this can make it more clear what happens:

rule "Auto Solar Power Usage scenes"

when
	Item Inverter_Generation_Combined changed or
	Item Inverter_1_Grid changed
	then
		logInfo("Auto Solar Power Usage scene", "Rule triggered")
		if (Auto_Solar_Power_Usage_scenes_Running.state == OFF) {
			Auto_Solar_Power_Usage_scenes_Running.sendCommand(ON)
			logInfo("Auto Solar Power Usage scene", "Rule running switch on")
			createTimer(now.plusSeconds(5), [ | // Timer 1
		
				if (Inverter_1_Grid.state > 1000) {
					logInfo("Auto Solar Power Usage scene", "scene 0")
					Auto_Solar_Power_Usage.sendCommand(0)
		
					if (Inverter_1_Grid.state < -2500) {
						logInfo("Auto Solar Power Usage scene", "scene 1")
						Auto_Solar_Power_Usage.sendCommand(1)
						createTimer(now.plusSeconds(30), [ | // Timer 2
		
						if (Inverter_1_Grid.state < -3000) {
							logInfo("Auto Solar Power Usage scene", "scene 2")
							Auto_Solar_Power_Usage.sendCommand(2)
							createTimer(now.plusSeconds(300), [ | // Timer 3
		
								if (Inverter_1_Grid.state < -4500) {
									logInfo("Auto Solar Power Usage scene", "scene 3")
									Auto_Solar_Power_Usage.sendCommand(3)
									createTimer(now.plusSeconds(30), [ | // Timer 4

									]) // End timer 4
								} // End if  (Inverter_1_Grid.state < -4500)
							]) // End timer 3
						} //End if (Inverter_1_Grid.state < -3000)
					]) // End timer 2
				} // End if (Inverter_1_Grid.state < -2500)
			}  // End if (Inverter_1_Grid.state > 1000)
		]) // End timer 1
		logInfo("Auto Solar Power Usage scene", "Rule running switch off")
		Auto_Solar_Power_Usage_scenes_Running.sendCommand(OFF)
	} // End if (Auto_Solar_Power_Usage_scenes_Running.state == OFF)
end

thanks for all the help guys.

Here’s what ive got now.

rule "Auto Solar Power Usage scenes"

when
	Item Inverter_Generation_Combined changed or
	Item Inverter_1_Grid changed
	then
	if		(Auto_Solar_Power_Usage_scenes_Running.state !== ON)
				{
			logInfo("Auto Solar Power Usage scene","Inverter_1_Grid {}", Inverter_1_Grid.state)

			logInfo("Auto Solar Power Usage scene", "Rule triggered")
		Auto_Solar_Power_Usage_scenes_Running.sendCommand(ON)
			logInfo("Auto Solar Power Usage scene", "Rule running switch on")
		createTimer(now.plusSeconds(5), [ |
			logInfo("Auto Solar Power Usage scene", "First Timer Completed")
		
		if		(Inverter_1_Grid.state > 1000)
				{
			logInfo("Auto Solar Power Usage scene", "scene 0")
		Auto_Solar_Power_Usage.sendCommand(0)
				}
		if		(Inverter_1_Grid.state < -2500)
				{
			logInfo("Auto Solar Power Usage scene", "scene 1")
		Auto_Solar_Power_Usage.sendCommand(1)
		createTimer(now.plusSeconds(30), [ |
		

		if		(Inverter_1_Grid.state < -3000)
				{
			logInfo("Auto Solar Power Usage scene", "scene 2")
		Auto_Solar_Power_Usage.sendCommand(2)
		createTimer(now.plusSeconds(300), [ |
		

		if		(Inverter_1_Grid.state < -4500)
				{
			logInfo("Auto Solar Power Usage scene", "scene 3")
		Auto_Solar_Power_Usage.sendCommand(3)
	
	
	 }
	]) }
	]) 
			logInfo("Auto Solar Power Usage scene", "Rule running switch off")
	Auto_Solar_Power_Usage_scenes_Running.sendCommand(OFF)
	}  ]) 
	}
end

What I’m trying to achieve here is. if the house is using more than 1000w from the grid with power then activate scene 0

If the solar pv is making more than the house is using then once it hits -2500 activate scene 1 which turns the hot water cylinder on which is a resistance heater so the load chance is instant. wait 30 seconds and if the house still has an excess of power of more than -3000 then activate scene 2 which turns the house heating on. this is 2 heat pumps which have a ramp up time so it needs to wait 5 mins to allow them to get unto speed. after its waited 5 mins then check the power usage again and if it is above -4500 and if it is turn the spa heating on.

As the rule is at the moment it stalls after the first timer of 5 seconds and doesn’t check the next if condition

if		(Inverter_1_Grid.state > 1000)

One problem is that while the timer is waiting these 5 minutes the state of Inverter_1_Grid will probably change, causing the rule to run again, creating another timer and so on. The Auto_Solar_Power_Usage_scenes_Running switch should be on until all timers have completed to prevent this. Otherwise this version seems to do what you want.

I’m pretty sure this is not what you want to achive.
You don’t need any timer, instead you will need persistence. Do a persistence to Inverter_1_Grid, then use this rule:

rule "Auto Solar Power Usage scene"
when
    Item Inverter_1_Grid changed
then
    var Number nPower = 0
    var Numver nSceneNew = -1
    if(Inverter_1_Grid.maximumSince(now.minusSeconds(5)).state instanceof Number) {
        nPower = (Inverter_1_Grid.maximumSince(now.minusSeconds(5)).state as Number).floatValue
        logInfo("autoSolarScene", "maximum power consumption since 5 Seconds: {}",nPower)
        if(nPower > 1000 && Auto_Solar_Power_Usage.state != 0)
            nSceneNew = 0
        if(nPower < -2500 && Auto_Solar_Power_Usage.state == 0)
            nSceneNew = 1
    }
    if(Inverter_1_Grid.maximumSince(now.minusSeconds(30)).state instanceof Number) {
        nPower = (Inverter_1_Grid.maximumSince(now.minusSeconds(30)).state as Number).floatValue
        logInfo("autoSolarScene", "maximum power consumption since 30 Seconds: {}",nPower)
        if(nPower < -3000 && Auto_Solar_Power_Usage.state == 1)
            nSceneNew = 2
    }
    if(Inverter_1_Grid.maximumSince(now.minusSeconds(300)).state instanceof Number) {
        nPower = (Inverter_1_Grid.maximumSince(now.minusSeconds(300)).state as Number).floatValue
        logInfo("autoSolarScene", "maximum power consumption since 300 Seconds: {}",nPower)
        if(nPower < -4500 && Auto_Solar_Power_Usage.state == 2)
            nSceneNew = 3
    }
    if(nSceneNew > -1 && nSceneNew != Auto_Solar_Power_Usage.state) {
        logInfo("autoSolarScene", "Switching to Scene {}",nSceneNew)
        Auto_Solar_Power_Usage.sendCommand(nSceneNew)
    }
end

The rule will trigger whenever Inverter_1_Grid changed. Now the rule does a lookup if the maximum power consumption of the last 5 seconds was above 1000 or under -2500. If so (and the active scene is correct, so not 0 for +1000, 0 for -2500) it does change the scene by setting nSceneNew to a value 0 or 1.
after that it does the same for 30 seconds maximum and 300 seconds maximum, with other boundaries and other active scene number.

EDIT: Changed code slightly

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.