HowTo: Get notified on empty batteries

val lowBatteriesList

... lowBatteryList.

The variable is plural but when the variable is attempted to be used it is singular “Battery”.

Change to

val lowBatteryList = gBatteries...

That should clear up all the warnings. If not., add types to the filter.

.filter[ NumberItem b | b.state < 20 ].map[

Thanks

i made those changes and this is the message now:

06:53:11.719 [INFO ] [del.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'batteries.rules', using it anyway:
There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures into a typed context.
Assignment to final parameter
06:53:11.722 [INFO ] [del.core.internal.ModelRepositoryImpl] - Loading model 'batteries.rules'


Rule:

rule "Low battery alert"
when
    Item gBatteries changed
then
    if(gBatteries.state > 20) return;

    val lowBatteryList = gBatteries.members.filter[ NumberItem b | b.state < 20 ].map[ name ].reduce[ list, bat | list = list + ", " + transform("MAP", "batteries.map", bat) ]
    sendBroadcastNotification("The following batteries need to be replaced: " + lowBatteryList.subString(0, lowBatteryList.size-2) + ".")
end


Hmmm. the last one doesn’t make much sense.

The only other lambda missing a type that makes any sense is the reduce, so I guess add some Types there:

reduce[ String list, String bat | list = ...

Its improving :slight_smile:

lol!

06:58:39.112 [INFO ] [del.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'batteries.rules', using it anyway:
Assignment to final parameter
06:58:39.133 [INFO ] [del.core.internal.ModelRepositoryImpl] - Refreshing model 'batteries.rules'

It shouldn’t be a problem And like I said, these are warnings, not errors. The Rule will run. The only other thing one can change is the val to a var.

OK. It may be a bit too complex for my liking :slight_smile:

Thanks Rich, ill see if it works

Hi Rich

Unfortunately it does not work, if i update the group to 10 I get no notifications.

Does the Rule trigger? Add logging to make sure.

How are you updating the Group to 10? I don’t know if you can postUpdate to a Group, particularly one that uses an aggregation function like MIN and have the update take.

Ive changed the rule to be more like a prevuious poster in this thread, it looks like this now:

rule "Low battery alert"
when
    Item gBatteries changed
then
    if(gBatteries.state > 20) return;

    val lowBatteriesList = gBatteries.members.filter[ b | b.state < 20 ].map[ label ].reduce[ s, label | s + ", " + label ]
    sendBroadcastNotification("The following batteries need to be replaced:", lowBatteriesList.toString)
end

It runs correctly and I get an alert but it doesnt print the val into the alert correctly (ie it doesnt tell me which battery is low when i set it to 10)

Well, if the filter doesn’t return any results then there is nothing to perform the map and reduce on. How are you triggering the Rule and do you for sure have one whose state is < 20?

Im sending a manual update to the individual item using the console to trigger the rule.

Break down the map reduce line, logging at each step to see what the filter is returning, then the map, then the reduce.

Thats a bit complex for m (breaking it down etc) as I dont understand ‘filter’

I put your original rule back in, triggered it and now

09:14:41.104 [ERROR] [untime.internal.engine.RuleEngineImpl] - Rule 'Low battery alert': 'subString' is not a member of 'java.lang.String'; line 7, column 81, length 54

I dont understand why it works on your system and not mine if the rule you posted is verbatim from your machine.

Bit out of my depth to troubleshoot, Thanks anyway Rich! ill see if I can find a simplier example :slight_smile:

I use this:

val Number lowBatteryThreshold = 15

rule "Battery Monitor"
when
    Time cron "0 55 10 * * ?"
then
    if (!Batteries.allMembers.filter( [ battery | (battery.state as Number) <= lowBatteryThreshold ] ).empty) {
        val String report = Batteries.allMembers.filter( [ b | (b.state as Number) <= lowBatteryThreshold ] ).sortBy( [ bat | bat.state as Number ] ).map[ name + ": " + state.toString ].join("\n")
        val message = "Battery levels:\n\n" + report + "\n\nRegards,\n\nOur House"
        sendMail("vzorglub@gmail.com", "Low battery alert !", message)
    }
end

In your case Batteries will be gBatteries

I tried yours too Vincent, it doesnt work for me. It wont display the contents of message


val Number lowBatteryThreshold = 20

rule "Battery Status Check"
when
    Item gBatteries changed
then
    if (!gBatteries.allMembers.filter( [ battery | (battery.state as Number) <= (lowBatteryThreshold) ] ).empty) {
        val String report = gBatteries.allMembers.filter( [ (state as Number) <= (lowBatteryThreshold) ] ).sortBy( [ state as DecimalType ] ).map[ name + ": " + state.format("%d%%") ].join("\n")
        val message = "Battery levels:\n\n" + report + "\n\nRegards,\n\nOur House"
      sendBroadcastNotification("Battery Report","The following batteries need to be replaced : " + message)
    }
end

val Number lowBatteryThreshold = 20

rule "Battery Status Check"
when
    Item gBatteries changed
then
    if (!gBatteries.allMembers.filter( [ battery | (battery.state as Number) <= (lowBatteryThreshold) ] ).empty) {
        val String report = gBatteries.allMembers.filter( [ (state as Number) <= (lowBatteryThreshold) ] ).sortBy( [ state as DecimalType ] ).map[ name + ": " + state.format("%d%%") ].join("\n")
        logInfo("REPORT", report)
        val message = "Battery levels:\n\n" + report + "\n\nRegards,\n\nOur House"
      sendBroadcastNotification("Battery Report","The following batteries need to be replaced : " + message)
    }
end

logs?

rule "Battery Status Check"
when
    Item gBatteries changed
then
    if (!gBatteries.allMembers.filter( [ battery | (battery.state as Number) <= (lowBatteryThreshold) ] ).empty) {
        val String report = gBatteries.allMembers.filter( [ (state as Number) <= (lowBatteryThreshold) ] ).sortBy( [ state as DecimalType ] ).map[ name + ": " + state.format("%d%%") ].join("\n")
        logInfo("REPORT", report)
        val message = "Battery levels:\n\n" + report + "\n\nRegards,\n\nOur House"
      sendBroadcastNotification("Battery Report","The following batteries need to be replaced : " + message)
    } else {
        logInfo("REPORT: ", "EMPTY")
    }
end

Just in case… Logs?

1 Like

None… This occurs when I change the values

09:51:42.657 [INFO ] [smarthome.event.ItemStateChangedEvent] - LivingRoom_FibButton_Battery changed from 10 to 100
09:51:42.659 [INFO ] [home.event.GroupItemStateChangedEvent] - gBatteries changed from 10 to 100 through LivingRoom_FibButton_Battery
09:51:45.292 [INFO ] [smarthome.event.ItemStateChangedEvent] - LivingRoom_FibButton_Battery changed from 100 to 10
09:51:45.294 [INFO ] [home.event.GroupItemStateChangedEvent] - gBatteries changed from 100 to 10 through LivingRoom_FibButton_Battery

I then see this, it reports the state in the console but the Notification i get on my phone only has ‘Battery Report’ and then nothing

09:53:18.602 [INFO ] [smarthome.event.ItemStateChangedEvent] - LivingRoom_FibButton_Battery changed from 100 to 10
09:53:18.604 [INFO ] [home.event.GroupItemStateChangedEvent] - gBatteries changed from 100 to 10 through LivingRoom_FibButton_Battery
09:53:18.609 [INFO ] [eclipse.smarthome.model.script.REPORT] - LivingRoom_FibButton_Battery: 10%

The logInfos do not display.