[SOLVED] Rule to check power consumption over a period of time

I’m a little stuck as to how to check is something is in use over a time window.

Situation:

A cleaning cycle lasts about 20 minutes and involves high power use (motor running), and moments of lower power use/looks like it’s doing nothing.

What’s the best way to think about a rule that would evaluate power consumption over say a 20 minute window? So that I can safely disable power without it being half way through a cleaning cycle?

Something with the timeout binding? Any pointers to similar rules would be most welcome.

Here’s a starter rule that will check if the cleaning cycle is running by checking the current consumption at 9pm and turn the power off if no cleaning cycle.
If a cleaning cycle has started then a proxy item will use the expire binding and start a timer for 20 min. after the 20 min when the Proxy_Timer changes to off the rule runs again to turn power off.
The second rule will turn the power back on at 9am.

NOTE: To use the Proxy_Timer you will need to install the Expire binding thru PaperUI
Change all item names as needed.

Items

Switch Switch_item "Your Power Switch"
Number Switch_Power "Power Consumption"
Switch Proxy_Timer { expire="20m, command=OFF" }

Rule

rule "TurnOffPower"
when
	Time cron "0 0 21 ? * *" or              //OFF at 9 pm everyday
        Proxy_Timer changed from ON to OFF
then

        var Number power = Switch_Power.state as Number

        if(power > 2){                  // adjust the power level as needed
        Proxy_Timer.sendCommand(ON)    // turn on timer with expire binding for 20 min
    }

        else(Proxy_Timer.state == OFF){
            Switch_item.sendCommand(OFF)   // turn power off if no cleaning cycle
    }
end

rule "TurnOnPower"
when
	Time cron "0 0 9 ? * *"    // power on at 9am every day
then
       Switch_item.sendCommand(ON)
end

Thanks @H102 - that’s perfect. I’ve adapted it and am watching the event log now. Cheers.

1 Like

Your Welcome.

Can you manually start a cleaning cycle? If so, change the cron time to power off as something closer to the actual time and start the clean cycle. You can also replace the Switch_Item with a dummy Switch_dummy item for testing, that way no harm if the rule fails and turns the Switch_Item off while cleaning.

@imaginator There is also a power consumption example setup here: Washing Machine State Machine

You can take some ideas from there also but I believe that @H102 rule will work just fine for your use case.

So I had a chance to test this out. Unfortunately the timer element doesn’t seem to be triggering.

rule "TurnOffCatGeniePower"

when
	Time cron "0 54 13 ? * *" or 
	Item CatGenieTimer changed from ON to OFF
then
    var Number CatGenieWatts = CatGeniePower.state as Number
    if(CatGenieWatts > 1){                       	// adjust the power in watts as needed
        CatGenieTimer.sendCommand(ON)    	// turn on timer with expire binding for 20 min
    }
    else(CatGenieTimer.state == OFF){
        CatGenieSwitch.sendCommand(OFF)   		// turn power off if no cleaning cycle
    }
end

rule "TurnOnCatGeniePower"
when
	Time cron "0 0 9 ? * *"    				// power on at 9am every day
then
    CatGenieSwitch.sendCommand(ON)
end

In the log I see:

==> /var/log/openhab2/events.log <==                                                                                                                                         
2018-11-28 13:54:00.062 [ome.event.ItemCommandEvent] - Item 'CatGenieTimer' received command ON                                                                         
2018-11-28 13:54:00.091 [ome.event.ItemCommandEvent] - Item 'CatGenieSwitch' received command OFF
2018-11-28 13:54:00.311 [vent.ItemStateChangedEvent] - CatGenieSwitch changed from ON to OFF

I also setup the following items:

Switch   CatGenieTimer                "Switch"         {expire="20m,command=OFF"}
Switch   CatGenieSwitch               "Switch"         {channel="tplinksmarthome:hs110:CatGenie:switch"}
Number   CatGeniePower                "Power"          {channel="tplinksmarthome:hs110:CatGenie:power"}

I’m testing this on a lamp that draws ±5 watts: starting the rule off, with the lamp on, the lamp is immediately turned off.

I’m also not quite sure how this rule would deal with the situation of, at 9pm, running and being in the middle of a “do nothing”/don’t draw any power, part of the cleaning cycle. To better understand the cleaning cycle it’s something like “rotate the bowl”, “scoop the bowl”, do nothing for about 30 seconds, more scooping, more washing, more doing nothing. etc. Any ideas on how to deal with this situation?

Would simply firing the Expire timer for 20 mins every time the power use drops below 5W be a sensible way to go about this. Having said that, every now and again it’s useful to run an extended cleaning cycle (about 60 mins).

Make a change to the else and add else if like below. This should specify to test the condition before executing the command to turn the Switch off.

else if(CatGenieTimer.state == OFF){
2018-11-28 13:54:00.062 [ome.event.ItemCommandEvent] - Item 'CatGenieTimer' received command ON                                                                         
2018-11-28 13:54:00.091 [ome.event.ItemCommandEvent] - Item 'CatGenieSwitch' received command OFF

Looks like .029 seconds between Timer on and Switch off.
If changing the code doesn’t work then a short thread sleep may be needed to allow the item state enough time to update and prevent turning off.
If thread sleep is needed add like below.

then
    var Number CatGenieWatts = CatGeniePower.state as Number
    if(CatGenieWatts > 1){                       	// adjust the power in watts as needed
        CatGenieTimer.sendCommand(ON)    	// turn on timer with expire binding for 20 min
        Thread::sleep(1000)                     // sleep for 1 second
    }
    else(CatGenieTimer.state == OFF){
        CatGenieSwitch.sendCommand(OFF) 

Test the rule using the modifications above, need to make sure the Switch is not powered off each time. I’ll do some thinking on how to modify for the “do nothing” time periods of the cleaning cycle.:thinking:

Modified rule to check the average power over a 3 minuet time period. This should take care of the “do nothing” time in the cleaning cycle. This should also address the extended cleaning cycle as well.

I thought about removing the timer since the rule will control the switch based on average power, but leaving it will add 20 minutes of extra protection.

NOTE: To use the average CatGeniePower this item needs to be added to your persistence file.
Example using rrd4j persist

Strategies {
	// for rrd chart cron strategy every minute
	everyMinute : "0 * * * * ?"
	// get data reduced for older values to keep database small
	everyHour : "0 0 * * * ?"
	everyDay : "0 0 0 * * ?"

	default = everyChange
}
Items {

	CatGeniePower : strategy = everyUpdate, everyMinute, restoreOnStartup
}

Rule

rule "TurnOffCatGeniePower"

when
	Time cron "0 54 13 ? * *" or 
	Item CatGeniePower changed 
then
//    Add persistence to CatGeniePower item 
    if(CatGeniePower.averageSince(now.minusMinutes(3)) > 1){     // adjust time and watts as needed
        CatGenieTimer.sendCommand(ON)    	// turn on timer with expire binding for 20 min
//	Thread::sleep(1000)                 // un-comment if needed to allow switch state to update
    }
    else if(CatGenieTimer.state == OFF){
        CatGenieSwitch.sendCommand(OFF)   		// turn power off if no cleaning cycle
    }
end

rule "TurnOnCatGeniePower"
when
	Time cron "0 0 9 ? * *"    				// power on at 9am every day
then
    CatGenieSwitch.sendCommand(ON)
end
1 Like

Hi, found this very promising code example here for my TV powerstrip. My goal is to turn off the powerstrip after a certain amound of time but only if it isn’t turned on again. I abstracted it for my needs but getting an error at the “>” operator.
Persistence

Strategies {
	everyMinute : "0 * * * * ?"
	default = everyChange
}
Items {
	SonoffPow01Consumption : strategy = everyUpdate, everyMinute, restoreOnStartup
}

Rule

rule "Powerstrip TV standby off"
when
    Item SonoffPow01Consumption changed
then
    if (SonoffPow01Consumption.averageSince(now.minusMinutes(10)) < 20){
    SonoffPow01PowerSwitch.sendCommand(OFF)
    }
end

Error message:

Ambiguous binary operation.
The operator declarations
	operator_lessThan(Number, Number) in NumberExtensions and
	operator_lessThan(Type, Number) in NumberExtensions
both match.(org.eclipse.xtext.xbase.validation.IssueCodes.ambiguous_feature_call)

Is there a way to get rid of this error?