Battery tracking

Stay updated on low battery and devices that do not report.

Every hour I run a homeyscript to check battery status, and look for devices that have not reported last 24 hours. If the list of affected devices do differ from previous run, it will send a battery status report to a Telegram group like this:

Preparing better logic variables

First create two better logic string variables, batterytext and batterystatus.

It does not matter what value you set.

Create a homeyscript

batteryStatus2.js
let betterlogic = await Homey.apps.getApp({id: "net.i-dev.betterlogic"})
let getVar = async (name) => {
    let x = await betterlogic.apiGet(name)
    if (!x)  throw new Error("Could not find variable [" + name + "]")
    return x.value
}

let currentStatus = await getVar('batterystatus')

const devicesX = await Homey.devices.getDevices();
const devices = []
_.forEach(devicesX, device => {
    devices.push(device)
})

const excludes = ['75602d03-9c02-4ad4-a29f-119313982878']

const isBattery = (x) => {
    if (!x.hasOwnProperty('capabilities')) return false
    if (_.includes(excludes, x.id) ) return false
    return _.includes(x['capabilities'], 'measure_battery')
}
const lowBattery = (x) => {
    if (x.up > (24*3600)) return true
    if (x.battery < 35) return true
    return false
}

const sf = (str) => {
    return str.replace(/ /g, "\\ ")
}

const getIDstring = (entities) => {
    let ids = _.map(entities, (x) => { return x.id })
    ids = _.sortBy(ids)
    console.log(ids)
    return ids.join(',')
}


const batteryInfo = (x) => {
    let info = {
        name: x.name,
        id: x.id,
        battery: null,
        driverUri: x.driverUri,
        driverId: x.driverId,
        batteries: x.energyObj.batteries
    }


    if (x.capabilitiesObj && x.capabilitiesObj.hasOwnProperty('measure_battery')) {
        //console.log(x)
        info.battery = x.capabilitiesObj.measure_battery.value

        let updates = []
        for (let key in x.capabilitiesObj) {
            if (x.capabilitiesObj[key].lastUpdated) updates.push(Date.parse(x.capabilitiesObj[key].lastUpdated))
        }
        let mostRecent = _.max(updates)
        // Seconds since last updated measurement from this entity
        info.up = Math.floor((Date.now() - mostRecent)/1000.0)

        
    }
    info.lowBattery = (info.battery < 50)
    info.noUpdateToday = (info.up > (24*3600))
    info.alarm = (info.up > (24*3600)) || (info.battery < 35)

    info.body = "battery,id=" + sf(info.id) + ",name=" + sf(info.name) + " battery=" + info.battery + ",upd=" + info.up + 
        ",lowbatt=" + info.lowBattery + ",noupd=" + info.noUpdateToday + ",alarm=" + info.alarm + "\n"

    return info
}


let batteryentities = _.filter(devices, isBattery)
batteryentities = _.map(batteryentities, batteryInfo)
batteryentities = _.filter(batteryentities, (x) => { return x.alarm })

// console.log(batteryentities)

let batterytext = ''
_.forEach(batteryentities, batt => {

    if (batt.lowBattery) {
        batterytext += batt.name + ' has low battery ' + batt.battery + '%' + "\n"
        console.log(batt.name + ' has low battery ' + batt.battery + '%')
    } else if (batt.noUpdateToday) {
      batterytext += batt.name + ' has not reported today. Not in ' + Math.floor(batt.up/3600) + ' hours' + "\n"
      console.log(batt.name + ' has not reported today. Not in ' + Math.floor(batt.up/3600) + ' hours')
    }

    
})


let batterystatus = getIDstring(batteryentities)
if (currentStatus !== batterystatus) {

  console.log(" ----- REPORTING -----")
  betterlogic.apiPut("batterytext/" + encodeURIComponent(batterytext))

} else {
  console.log(" - no report - ")
}


console.log("Store batterystatus: " + batterystatus)
betterlogic.apiPut("batterystatus/" + batterystatus)

return true

Create the neccessary flows

You will need two flows. One flow that runs the battery script regularly:

And one script that sends the prepared battery status message to telegram when it is updated:

The second action of the script above is to update a dakboard status display with the same message.

Last updated