Hereās how my setup looks like:
I have two groups related to battery powered devices: gBatteryLevels (group of items that report their values as number, battery level) and gBatteryWarning (items that report only when the battery is low).
Group gBatteryLevels (gSensors)
Group:Switch:OR(ON,OFF) gBatteryWarning (gSensors)
Most of my devices report both type of items, but some of them report only level of the battery, therefore, the first rule unifies this and fills the missing gBatteryWarning itemsā¦ Item naming is as follows:
Number MyDeviceBattery "Battery [%.1f %%]" <battery> (gMyRoom) { channel="..." }
Switch MyDeviceBatteryLow "Low battery" <lowbattery> (gMyRoom, gBatteryWarning) { channel="..." }
but in case the item is missing the āLowā item, then it will be assigned to a group and itāll be defined like this:
Number MiFloraBattery "Sensor Battery Level [%d %%]" (gMyRoom, gBatteryLevels) { channel="..." }
// this is a virtual item needed for later use
Switch MiFloraBatteryLow "Low battery" <lowbattery> (gMyRoom, gBatteryWarning)
Now, the .rules file handling all of thisā¦
rule "Convert gBatteryLevels (number) to gBatteryWarning (switch)"
when
Member of gBatteryLevels changed
then
val device = triggeringItem
val Number batteryValue = device.state as DecimalType
val String batteryLowName = device.name+"Low"
if(batteryValue <= 15) sendCommand(batteryLowName, 'ON')
else postUpdate(batteryLowName, 'OFF')
end
And finally the main rule that does the alertingā¦
rule "Low battery alert"
when
Member of gBatteryWarning changed to ON
then
val StringBuilder devices = new StringBuilder
val triggeredDevices = gBatteryWarning.members.filter[ b | b.state == ON ]
triggeredDevices.forEach[ device, index |
var deviceMappedName = transform("MAP", "batteryDevices.map", device.name)
if (triggeredDevices.size > 1) {
if (index == triggeredDevices.size-1) devices.append(deviceMappedName + ".")
else devices.append(deviceMappedName + ", ")
} else {
devices.append(deviceMappedName)
}
]
sendBroadcastNotification("Low battery alert for: " + devices.toString)
end
I borrowed @rlkoshakās idea of mapping some human-readable device names so iām using a .map fileā¦
I hope someone will find this useful.