[SOLVED] Battert low rule misfiring

Hi,
i have a rule that supposed to email me when some battery is low.
It worked fine, but now it seems it went crazy and it emails me every time some battery changes.
WHen I inspect the event log, I see a battery changed to 70. And it was accused that is low (should be lower then 19).

here is my rule
(btw I read something about triggeringItemName was deprecated. its true? for me it stil works, in the email alert I get notified which sensor is low on battery. But maybe thats the reason it doesnt work well. should I use some other commands?

rule "Battery Low Alert"
when
    Item BalconyBattery changed or 
    Item LivingBattery changed or 
    Item KidsBattery changed or 
    Item BedroomBattery changed or 
    Item EntranceDoorBattery changed or 
    Item Balcony1DoorBattery changed or 
    Item Balcony2DoorBattery changed or
    Item FingerbotBattery changed or
    Item VentilationBattery changed
then
    if(BalconyBattery.state < 19 || LivingBattery.state < 19 || KidsBattery.state < 19 || BedroomBattery.state < 19 || EntranceDoorBattery.state < 19 || Balcony1DoorBattery.state < 19 || Balcony2DoorBattery.state < 19 || VentilationBattery.state < 2)
      {val mailActions = getActions("mail","mail:smtp:balkon")
      mailActions.sendMail("address@server.com", "openHAB Alert - Battery Low", "Battery low for sensor " + triggeringItemName)}
end

You probably need to convert the state to a numeric value (probably based on a UoM, which I am guessing would be in percent units ( or unit “one”)) before you do the logical value check.

can I use Item.state.toNumber instead of defining them all as variables “as Number” ?

Try something like the following (I am not 100% sure about the syntax)…

if (19 > (Item.state as
QuantityType<?>).toUnit(“percent”).doubleValue) {

Some additional info…

First, triggeringItemName is not deprecated.
Second, a better way to do this would be to use a Group Item, e.g. like this:

// global val has to be defined on top the file
val HashMap<String, Number> hmBatteryThreshold = newHashMap(
                                                    BalconyBattery ->      19,
                                                    LivingBattery ->       19,
                                                    KidsBattery ->         19,
                                                    BedroomBattery ->      19,
                                                    EntranceDoorBattery -> 19,
                                                    Balcony1DoorBattery -> 19,
                                                    Balcony2DoorBattery -> 19,
                                                    FingerbotBattery ->    19,
                                                    VentilationBattery ->   2
                                                 )

rule "Battery low alert"
when
    Member of gBattery changed
then
    var strMessage = "Battery low for sensor "
    gBattery.members.filter[i|(i.state as Number).intValue < hmBatteryThreshold.get(i.name)].forEach[j|
        strMessage = strMessage + j.name + " (" + j.state.toString + ") "
    ]
    if(strMessage.size >  25) {
        val mailActions = getActions("mail","mail:smtp:balkon")
        mailActions.sendMail("address@server.com", "openHAB Alert - Battery Low", strMessage)
    }
end

Each Item in question has to be a member of the Group gBattery.
The hashMap is for the threshold, because one value is very different.
Be aware that the rule will create many emails when at least one battery is low. There may be options to reduce the amount of emails, e.g. start a timer and check if it’s still runnning before sending another email.

EDIT: corrected typo in code

I run a battery check that emails only if low only once a day and a full battery check status once a week email.

hi,
what about this?
OH3 triggeringitem deprecated - Any workaround/replacement? - Setup, Configuration and Use / Migration - openHAB Community

what about triggeringItem.state ? I think it doesnt work…

OK, I created a group for all battery items.
what about this simple rule?

rule "Battery Low Alert"
when
    Member of gBattery changed 
then
	if(triggeringItem.state < 19 )
       {val mailActions = getActions("mail","mail:smtp:balkon")
      mailActions.sendMail("email@email.com", "openHAB Alert - Battery Low", "Battery low for sensor " + triggeringItemName)
      }

end

in case triggeringItem.state is deprecated, what about this (found in the forum):

rule "Battery Status Check"
when
    Time cron "0 0 17 * * ?"
then
    var String msg = ""
    var triggertDevices = gBattery.members.filter[s|s.state <= 20]

    triggertDevices.forEach [ i |
        msg = msg + i.name + ': ' + i.state.toString + '%\n'
        logInfo("battery-check.rules","Low battery at " + i.name + ": " + i.state.toString + "%")
    ]

    if (msg != "") {
      sendMail("email@domain.com", "Battery warning", msg)
    }
end

I’m trying to find a simple way where I dont have to mention each sensor…

none of these rules work anymore, I tested it with threshold 80 and I dont get any alerts.
It seems DSL is on its way out…I’ll try to create a simple rule in GUI

EDIT: the last one works after all! just took some time
EDIT2: nope, still gets triggered for every battery update same as my original rule

OK finally got this rule working, there was some complication with Var string msg that I dont understand so I removed it.

working rule:

rule "Battery Low Alert"
when
    Member of gBattery changed
then
    var triggeredDevices = gBattery.members.filter[s|s.state < 20]
    triggeredDevices.forEach [ i |
        logInfo("battery-check.rules","Battery low for sensor " + i.name + ": " + i.state.toString + "%")
        val mailActions = getActions("mail","mail:smtp:balkon")
        mailActions.sendMail("email@email.email", "openHAB Alert - Battery Low", "Battery low for sensor " + i.name + ": " + i.state.toString + "%")]
end

It’s not.
But you’ll have to understand the difference between triggeringItem and triggeringItemName
The former is set to a genericItem if, and only if the rule gets triggered by Member of ..., while the latter is set to a string representing the triggering Item name if, and only if the rule was triggered by Item ...
So it’s up to the trigger, if one or the other is there.
In openHAB2, there was no triggeringItemName at all, but only triggeringItem for both kind of triggers.
That’s where the “deprecated” stuff comes from.
As said, if you want to get only one mail in a certain amount of time, use a timer:

// global var has to be defined on top the file
var Timer tMailAlert = null

rule "Battery low alert"
when
    Member of gBattery changed
then
    if(tMailAlert !== null) // message already sent, so return, !== is correct!
        return;

    var gDegraded = gBattery.members.filter[i|i.state < 20]

    if(gDegraded.size == 0) // no battery state under 20, so return
        return;

    val mailActions = getActions("mail","mail:smtp:balkon")
    var strMessage = "Battery low for sensor "

    gDegraded.forEach[j|             // build the list of degraded batteries
        strMessage = strMessage + j.name + " (" + j.state.toString + ") "
    ]

    mailActions.sendMail("address@server.com", "openHAB Alert - Battery Low", strMessage)
    tMailAlert = createTimer(now.plusHours(4),[|tMailAlert = null])
end

The former code had a tiny typo (as always… yes, it’s anoying).

1 Like

thanks!