Rule based socket deactivation (z-wave)

Hi everyone,

I’ve plugged this https://www.amazon.de/gp/product/B00PF0ZS8E between my wall socket and my dryer. I’m aiming at switching off the socket as soon as the measured power consumption falls below a certain threshold. I have the items set up as following:

Group Grp_UtilityRoom_Dryer_Socket    "Trockner"                        <socket>    (Grp_Sockets,Grp_Socket_GroundFloor,Grp_Socket_GF_UtilityRoom,GF_UtilityRoom)
Switch Dryer                           "Status"                        <socket>    (Grp_UtilityRoom_Dryer_Socket)              {zwave="2:command=switch_binary" }            
Number Dryer_Power                  "Leistung  [%.2f W]"                        (Grp_UtilityRoom_Dryer_Socket)              {zwave="2:command=meter,meter_scale=E_W"}
Number Dryer_Volts                  "Spannung [%.2f V]"                         (Grp_UtilityRoom_Dryer_Socket)              {zwave="2:command=meter,meter_scale=E_V"}
Number Dryer_Amps                   "Stromstärke [%.2f A]"                      (Grp_UtilityRoom_Dryer_Socket)              {zwave="2:command=meter,meter_scale=E_A"}
Number Dryer_Energy                 "Arbeit  [%.2f KWh]"                        (Grp_UtilityRoom_Dryer_Socket)              {zwave="2:command=meter,meter_scale=E_KWh" }

I can see the state changes during a dryer’s run in the UI as well as in the log files, e.g. in events.log:

2016-09-06 22:21:33 - Dryer_Power state updated to 0.93
2016-09-06 22:21:36 - Dryer_Power state updated to 0.988
2016-09-06 22:21:39 - Dryer_Power state updated to 1.053
2016-09-06 22:21:42 - Dryer_Power state updated to 0.906
2016-09-06 22:22:12 - Dryer_Power state updated to 0.851
2016-09-06 22:22:15 - Dryer_Power state updated to 1.004
2016-09-06 22:22:18 - Dryer_Power state updated to 0.834
2016-09-06 22:22:21 - Dryer_Power state updated to 1.033
2016-09-06 22:22:27 - Dryer_Power state updated to 1.112
2016-09-06 22:22:30 - Dryer_Power state updated to 0

However, for some mysterious reason I do not seem to be able to trigger actions upon these state changes from within a rule.
I have created a file Sockets.rules within the rules folder and (for testing purposes) set it up as following:

rule "dryer auto off"
    when
        Item Dryer_Power received update
    then
        sendCommand(Dryer, OFF)
end

From my understanding, it couldn’t be any simplier - Switch off the dryer when the power consumption changes. I’ve walked to my dryer a hundred times now switching it off and on again, but the dryer was never switched off automatically via the rule. I can trigger the dryer dying via the UI, so I’d guess the root of all evil residing somewhere within the “when” condition, but I cannot figure out where’s the mistake.
openhab.log doesn’t show up anything necessary at all, so I’m quite lost here and would very much appreciate some help on this.
In case I can deliver any further information, please let me know.
Many thanks in advance for your assistance!

Best regards

Not sure but try removing the whitespace before the when and then - I always have them with no indents. Also, add some logging to the rule to check if it is getting in there, to see if it is the rule trigger or the sendCommand perhaps?

Many thanks, @ben_jones12!
I’ve already tried to include some debug output, but I’m a bit confused about how to do this properly still and thus failed. I’ve tried the following:

import org.openhab.core.library.types.*

rule "dryer auto off"
when
Item Dryer_Power received update or
Item Dryer_Power changed
then
logDebug("sockets.rules", ":" +Dryer_Power.state as DecimalType)
end

In /etc/openhab/logback.xml and /etc/openhab/logback_debug.xml I’ve added the following:

<logger name="sockets.rules" level="DEBUG" />

/var/log/openhab.log still doesn’t show up anything unfortunately. That’s all I’ve done - Maybe I’m missing something here or searching in the wrong place…

Try this;

import org.openhab.core.library.types.*
import org.openhab.core.library.items.*
import org.openhab.model.script.actions.*

rule "Dryer off TEST"
when
    Item Dryer_Power received update
then
    logInfo("testing", "test log message")
    Dryer.sendCommand(OFF)
end

You should see the log message appearing in your standard openhab.log file.

Thank you, @ben_jones12!
I’ve copied and pasted your code into my rules file and started the dryer. In /var/log/openhab/openhab.log, I can only see the following though:

2016-09-07 12:35:54.562 [INFO ] [c.internal.ModelRepositoryImpl] - Refreshing model 'Sockets.rules'

I have not added anything to backlog.xml or backlog_debug.xml, but only adjusted the rules file.

As I did not get any proper output, I wanted to check if there’s a problem with the logger itself or if it’s the rule’s condition, so I also added the test logging in a different rules file that I’ve created for my lights. This looks as following now:

rule "All lights on"
    when
        Item Light_All received update ON
    then
            logInfo("testing", "test log message")
            sendCommand(Grp_Lights, ON)
end

When hitting the switch to turn on all lights, openhab.log does indeed print out the following:

2016-09-07 12:43:19.507 [INFO ] [g.openhab.model.script.testing] - test log message

Works like a charm. I guess that it’s now likely that it’s indeed the “when” condition of the rule preventing the log entry from being printed… Still can’t find the culprit though :frowning:

Next I would try moving that lighting rule into your socket rule file and see if it still fires - eliminate the file itself being the problem. Could be permissions (unlikely), or some odd line terminators (possibly), or it could be fine…

I did as you said and the message is still printed out properly. I’ve also tried it vice versa (moving the rule from the sockets rule file into the lights rule file) and the message isn’t printed out also from the lights rule file.Maybe there’s anything wrong with the item declaration of Dryer_Power that works fine in the UI but the state updates aren’t registered properly within a rule or something?

I may be wrong, but did you define the logger itself? I guess you can’t increase debug level of a non existent logger.

Hi @Udo_Hartmann,
many thanks for your input. I’m just beginning to understand how the logger works, so this is definitely worth taking a look at. As mentioned earlier, the approach brought up by @ben_jones12

logInfo("testing", "dryer energy changed!")

does already work out fine when using a different trigger (state of button that switches all lights on or off is changed). This works without any further definition, so this is all fine.

I have indeed defined a logger for the sockets in logback.xml and logback_debug.xml as following:

<logger name="sockets.rules" level="DEBUG" />

When trying the following, there is no output in openhab.log though:

logDebug("sockets.rules", "all lights switched on!")

Whereas when changing from logDebug to logInfo using the same logger, there is indeed output generated:

logInfo("sockets.rules", "all lights switched on!")

As I’ve defined the logger as a debug logger, I’m wondering why the output doesn’t show up in openhab.log when using logDebug rather than logInfo, but I think that this is a downstream topic as logInfo works out just fine for me.
I’d therefore expect the reason for the rules not being executed as desired residing within the condition in the “when” statement or the item declaration or so…

I’ve also tried to react upon the energy used by setting up an additional rule as following:

rule "Another Test"
when 
    Item Dryer_Energy received update or
    Item Dryer_Engergy changed
then
    logInfo("testing", "dryer energy changed!")
end

The corresponding item looks like this:

Number Dryer_Energy                 "Arbeit  [%.2f KWh]"                        (Grp_UtilityRoom_Dryer_Socket)              {zwave="2:command=meter,meter_scale=E_KWh" }

The result is the same as with Dryer_Power - Nothing is printed out when the value changes.

I thought the logger name would be org.openhab.model.script.sockets.rules or is it correct to omit the first part in logger definition? I have no experience in this :slight_smile:

There is a typo in the rule trigger - at least the second trigger is wrong (but received update should suffice your needs anyway)

You’re right, @Udo_Hartmann - Many thanks!
I’ve meanwhile apperently found the reason for the trigger not working: Apperently, the item state is not properly processed within a rule if there is a label and/or group assigned to it. I’ve introduced a new item holding the same data, but left out everything unnecessary in the definition. It looks like this:

Number Dryer_Power_Rule {zwave="2:command=meter,meter_scale=E_W"}

I was thereby able to read out the item changes properly and trigger my rules as intended.
In case anyone is interested, here’s also the corresponding rules for the new item:

/* imports */
import org.openhab.core.library.types.*
import org.openhab.core.library.items.*
import org.openhab.model.script.actions.*

/* pre-declarations */
var int dryerRunStatus = 0
var int thresholdDryerSwitchedOn = 1
var int thresholdDryerRunning = 100
var int statusDryerOff = 0
var int statusDryerSwitchedOn = 1
var int statusDryerRunning = 2


/* [RULES] */

rule "Dryer auto off"

when
    Item Dryer_Power_Rule received update 
then
    
    var dryerConsumption = Dryer_Power_Rule.state
    
    logInfo("dryer.rules", "dryer status changed (status: " + dryerRunStatus + "; consumption: " + dryerConsumption + ")")
    
    // dryer switched on
    if(dryerConsumption > 0 && dryerConsumption < thresholdDryerRunning && dryerRunStatus < statusDryerSwitchedOn) {
        dryerRunStatus = statusDryerSwitchedOn
        logInfo("dryer.rules", "dryer switched on!")
    // dryer run started
    } else if (dryerConsumption > thresholdDryerRunning && dryerRunStatus < statusDryerRunning) {
        dryerRunStatus = statusDryerRunning
        logInfo("dryer.rules", "dryer started running!")
    // dryer run finished
    } else if (dryerConsumption < thresholdDryerSwitchedOn && dryerRunStatus == statusDryerRunning) {
        logInfo("dryer.rules", "dryer finished running - terminating socket!")
        dryerRunStatus = statusDryerOff
        sendCommand(Dryer, OFF)
    }
end



rule "Dryer status switch UI update"

when
    Item Dryer_Power_Rule received update 
then

    if(dryerRunStatus > statusDryerOff && Dryer.state == OFF) {
        sendCommand(Dryer, ON)
    } else if(dryerRunStatus == statusDryerOff && Dryer.state == ON) {
        sendCommand(Dryer, OFF)
    }
end

I’ve moved the dryer stuff into an own rules file out of the sockets rules file, so this looks a bit different now. Just tested 3 different drying programs and it works like a charm :slight_smile:.

Many thanks again to you guys for help!