Rule to set the power usage (watts) back to 0 after item switched off. Rule to effect group of items

Hi All,

I’m wondering if someone could assist me with creating a rule? I’m happy to learn so any advice would be appreciated, many thanks.

Problem
I have lots of zwave switches which also measure the power consumption in watts. However quite often the result is registered but not set back to zero once the device is off. As a consequence I cannot accurately measure my power consumption.

My half solution
I have created a basic rule (I’m no expert) to reset the wattage when a particular switch is off.

rule "Heater reset watts"
when
	Item Swi_PO1_Heater received command OFF
then
    Num_PO1_Heater_Watts.postUpdate(0)
end

Preferred solution
I have 30 devices so rather than copy this code 30 times I was hoping I could create a rule that effects a group of items. That way I can simply add all and any future items to a group and it resets the wattage.

Here’s a rule I use to alert me when one of my battery devices needs a new battery. I didn’t write the rule myself, but have adapted it a little for my needs. Hopefully this will give you an idea.

rule "SYSTEM: Battery Alerts"
when
    Member of gBatteryLevel changed
then
val vDevice = triggeringItemName
if(triggeringItem.state == 100) {
    logInfo(logName, "System Message: The {} has been replaced.", vDevice)
}
val Number alertBatteryThreshold = 15
val Number lowBatteryThreshold = 10
var String msg = ""
if(gBatteryLevel.state > alertBatteryThreshold) return;
val alertBatteryList = gBatteryLevel.members.filter[ b | b.state < alertBatteryThreshold && b.state > lowBatteryThreshold ]
alertBatteryList.forEach [ i |
    msg = msg + i.name + ': ' + i.state.toString + '%\n'
    logInfo(logName, "System Message: Battery alert at " + i.name + ": " + i.state.toString + "%")
    if(now.getHour > 7 && now.getHour < 22) {
        Push_Notification.postUpdate("System Message: Battery alert at " + i.name + ": " + i.state.toString + "%")
    }
]
val lowBatteryList = gBatteryLevel.members.filter[ b | b.state < lowBatteryThreshold ]
lowBatteryList.forEach [ i |
    msg = msg + i.name + ': ' + i.state.toString + '%\n'
    logInfo(logName, "System Message: Low battery at " + i.name + ": " + i.state.toString + "%")
    if(now.getHour > 7 && now.getHour < 22) {
        Push_Notification.postUpdate("System Message: Low battery at " + i.name + ": " + i.state.toString + "%")
    }
]
end

In addition, this rule may also be helpful for you.

rule "SYSTEM: Which Sensor?"
when
    Member of gSensors changed
then
val int vTimeout = 10
val vLocation = triggeringItemName.split("_").get(0)
val vDevice = triggeringItemName.split("_").get(1)
val vType = triggeringItemName.split("_").get(2)
val vStatus = triggeringItem.state
var vItem = vLocation + "_" + vDevice + "_v" + vType
//var vActivation = vLocation + "_" + vType + "_Last_Activation"
//var vDate = new DateTimeType
if(vStatus == OFF && vType == "Motion") {
    createTimer(now.plusSeconds(vTimeout)) [|
        if(vStatus == ON && vType == "Motion") return;
    ]
}
if(vType == "Door" || vType == "Window") {
    postUpdate(vItem, vStatus.toString)
} else {
    sendCommand(vItem, vStatus.toString)
}
if(vLocation != "Garage") {
    logInfo(logName, "{}: {} Sensor has changed to {}", vLocation ,vType ,vStatus.toString)
}
end
1 Like

Many thanks for this, I’ll try to get my head around it to see if I can adapt for my use.

I think I’m almost there…

I’ve managed to create a variable from the name of my item and to change it to the name of the Number item that reports Watts. What I can’t figure out is how to then update the Number item to 0.

This is what I’ve done:

rule "Light Off then 0 Watts"
when
    Member of gLight changed
then
val vDevice = triggeringItemName
if(triggeringItem.state == OFF) {
    logInfo("", "Device Item: {} has turned OFF.", vDevice)
    val vLocation = triggeringItemName.split("_").get(1)
    val vDevType = triggeringItemName.split("_").get(2)
    var vItem = "Num_" + vLocation + "_" + vDevType + "_Watts"
    logInfo("", "Watts Item: {}", vItem)
    vItem.postUpdate(0) //this is the part I can't figure out
}
end 

Any idea what I’m doing wrong? I’m that clueless I don’t even know what to search on the forum…

Log:

[INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Swi_Bathroom_Lights' changed from ON to OFF
[INFO ] [org.openhab.core.model.script.      ] - Device Item: Swi_Bathroom_Lights has turned OFF.
[INFO ] [org.openhab.core.model.script.      ] - Watts Item: Num_Bathroom_Lights_Watts
[ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID '--WATT-1' failed: An error occurred during the script execution: Could not invoke method: org.openhab.core.model.script.actions.BusEvent.postUpdate(java.lang.String,java.lang.String) on instance: null in --WATT 

:roll_eyes: I’ve got it… I needed to add

.toString

to

vItem.postUpdate(0)

Working rule:

rule "Light Off then 0 Watts"
when
    Member of gLight changed
then
val vDevice = triggeringItemName
if(triggeringItem.state == OFF) {
    logInfo("", "Device Item: {} has turned OFF.", vDevice)
    val vLocation = triggeringItemName.split("_").get(1)
    val vDevType = triggeringItemName.split("_").get(2)
    var vItem = "Num_" + vLocation + "_" + vDevType + "_Watts"
    logInfo("", "Watts Item: {}", vItem)
    vItem.postUpdate(0.toString)
}
end

Thanks @Maximo what you sent was very helpful, I’ve learnt something today :beers:

1 Like

I’m pretty sure that even though that may not generate errors that is not working. You don’t have the Item. vItem is a String. Strings do not have postUpdate nor sendCommand. In fact, I’m not sure how that isn’t throwing errors even now.

There are two ways to update an Item, one way if you have the actual Item, which is what you are using, and other way when you only have the name of the Item. When you only have the name of the Item, you need to use the postUpdate Action.

postIUpdate(vItem, 0)

Seehttps://community.openhab.org/t/design-pattern-associated-items/15790 for more details.

When you look carefully at @Maximo’s second rule, you’ll see that he is using the postUpdate and sendCommand actions too.

I hesitated to comment because you asked for a rule, but I took another path. I don’t know if you are interested, but here goes.

All my watt measuring devices also provide a KWH reading. Even if the watt reading in OH is non-zero for an OFF device, the device “knows” it is OFF and the KWH reading will be accurate. The watt reporting (again with my devices) is set by a parameter, and I typically use different reporting intervals based on the device. I also generally have selective reporting, so the watt report is suppressed if it doesn’t change much. For KWH I poll (refresh) the devices at 23:59 to get a daily reading

I kind of went crazy (I don’t think I have saved what it cost) and have metering on the house Total as well as the big consumers. As for KWH the house Total is 99% of the utility company and the individual readings are about 97% of the total (I don’t measure a few things like the coffee makers and toasters.)
KWH meter vs house

I do have a few rules to refresh a meter if the watts are off on the major appliances (e.g. I refresh the house AC when the thermostat sends an OFF) rather than try to change the watt reading. However, my main focus was the KWH readings, so I accept some watt variability. Below is a chart of the house watts and the sum of all my other devices that provide watts. It is close enough for me as I do not use it for calculating KWH

Hi Rich,

Many thanks for your reply. I have tested it and strangely it does appear to be working. I tested using two items, I change the value of my Number item to 100 then switch the Switch item off and it does in fact change the Number value to 0

item

Interesting, thanks for your response. At some point I do want to go this far so I can accurately calculation the cost in GBP on a per item and per home basis.

Like you I will use KWH for this as I can see that it is a much more reliable measurement.

I am currently just using WATTS to roughly see how much I’m using and at what time.

Ideally I would like to enter my energy supplier cost per KWH into Grafana so I can see (as accurately as possible) how much my electricity costs.

Then something else is going wrong. There is simply no way that you can postUpdate to a String and have it do anything to the Item.