Help with Polling Battery for Thermostat (Custom Device Type)

First off, before buying my ST hub I have never looked at code before. So everything is new and the language is foreign to me.

I have a thermostat (CT100) that I need battery updates on because it is not connected to a C wire and I have no means of doing so. Also, it’s in a second home where I can’t monitor the physical device all the time. So seeing battery remotely provides significant peace of mind.

When I first installed the thermostat last weekend I was getting updates with the following code (provided by @minollo ). Please note that getBattery() is included in the def poll() command.


def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
def nowTime = new Date().time
state.lastBatteryGet = nowTime
def map = [ name: “battery”, unit: “%” ]
if (cmd.batteryLevel == 0xFF || cmd.batteryLevel == 0) {
map.value = 1
map.descriptionText = “$device.displayName battery is low!”
} else {
map.value = cmd.batteryLevel
}
map

private getBattery() { //once every 10 hours
def nowTime = new Date().time
def ageInMinutes = state.lastBatteryGet ? (nowTime - state.lastBatteryGet)/60000 : 600
log.debug "Battery report age: ${ageInMinutes} minutes"
if (ageInMinutes >= 600) {
log.debug "Fetching fresh battery value"
zwave.batteryV1.batteryGet().format()
} else “delay 87”
}


I was getting updates every 10 hours then all of a sudden it stopped working. My last battery update was 4 days ago, so I’m not sure if anything changed on the ST end. I read in a thread that the cmd.batteryLevel should have “as Integer” attached to the end. And I read in another thread that a sendEvent should be used because the polling command is inconsistent for a custom device type. Luckily, @RBoy wrote the code with both of these attributes. His code changed the one above to the one below:


def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
def nowTime = new Date().time
state.lastBatteryGet = nowTime
def map = [ name: “battery”, unit: “%” ]
if (cmd.batteryLevel == 0xFF || cmd.batteryLevel == 0) {
map.value = 1
map.descriptionText = "battery is low!"
sendEvent(name: “BatteryLevel”, value: “battery is low!”)
} else {
map.value = cmd.batteryLevel as Integer
sendEvent(name: “BatteryLevel”, value: “battery is $cmd.batteryLevel%”)
}
map
}

private getBattery() { //once every 10 hours
def nowTime = new Date().time
def ageInMinutes = state.lastBatteryGet ? (nowTime - state.lastBatteryGet)/60000 : 600
log.debug "Battery report age: ${ageInMinutes} minutes"
if (ageInMinutes >= 600) {
log.debug "Fetching fresh battery value"
zwave.batteryV1.batteryGet().format()
} else “delay 87”

}
def refresh() {
// Force a refresh
log.info "Requested a refresh"
state.lastBatteryGet = (new Date().time) - (600 * 60000)
poll()
}


Hitting the refresh button/tile on my phone multiple times does nothing to update battery. Also, when I look at the list of events on IDE (using the “from device” link) I see nothing relating to battery - although I see the multiple refreshes. I’ve installed the Pollster by smartapp by @geko and am polling the thermostat every 6 minutes. I’ve deleted and re-installed the smart device several times. I’m out of ideas.

Any help you can provide would be really appreciated. Thanks so much.

First up, try the instruction on this page. I too have a CT100 thermostat and I keep this page updated based on my own thermostats. Also remember that it can take upto 24 hours for the battery to update, even if you press the refresh button it can take time. It’s something to do with the underlying platform and I can’t seem to get any response from the support team on it. But the code works overall.

Second regarding your C-Wire I have the same issue, and I found 2 workaround, first one you can disconnect the G and use it for the C (remember to rewire on both ends) and then short the G and Y at hte thermostat end. This will get your power on the C to the thermostat but you lose fan control (ie the fan comes on when the heat/compressor comes on, but you can individually turn on/off fan, it’s completely automatic). If fan cycling isn’t important this it the easiest and cheapest. Other option is a splitter. Both are summarized here with diagrams:
http://www.hvacproblemsolver.com/new-thermostat.asp

Just a couple of comments:

  • Once the battery updates work, I have never noticed that they mysteriously stop working; the only reason for that, is if the thermostat “dies” because batteries died… And that can happen quite suddenly, more so with lithium than with alkaline batteries.
  • The way the battery refresh mechanism is implemented (or was originally implemented), it doesn’t request battery values each time poll() is called, but only if the current battery value is “stale”; so, hitting refresh multiple times (which translates into poll()), won’t do you any good. If you look at the log files for the device, you should see details about when the last battery value was processed.
  • Depending on how you try to see updated battery values, it may well happen that you don’t see anything until the battery value actually changes.

@RBoy yep that’s the code I was using from you :smile:

@minollo Your theory makes sense given the sequence of events for me. That is, I put in new alkaline batteries when I connected the new device and received a reading of 100% within the first 10 hours of use. The next reading was 99% when the report came back 10 hours later, at which point I switched to lithium batteries. I received a new battery value of 100% on the next update, with no further updates in the subsequent 4 days. So it could very well be the reading is still 100% with lithium batteries and nothing is reporting since nothing changed.

To test your theory I think I’ll throw some alkaline batteries back in when I’m up there this weekend and see what the response is over two days. If there was a 1% change last time (within a day), surely there would be a small change within two days with alkalines.

No need to do that; in ide.smartthings.com, inspect your thermostat device, and “List Events”; then click on “all” at the top; at that point you’ll see all events, whether they are updating information or not; you’ll see plenty of noise there, as all the polling events are there as well; but you should also see the battery events, if they worked.
And while you are there, also click on “Live Logging”, fire a refresh from your ST app for the thermostat, and see what the device logs.

Yeah when I view the list of “All” events the battery never shows up as an event (there sure is a ton of polling though!)

Thanks for the tip on the Live Logging. I never knew how to do that. Here’s what returned as it relates to battery:


Battery report age: 60.0008666667 minutes

Fetching fresh battery value

Parse returned [[name:battery, unit:%, value:100, isStateChange:false, displayed:false, linkText:Thermostat, descriptionText:Thermostat battery is 100%]]


And now I see where the state change you referred to is. So if the % hasn’t changed it must not be reporting. At minimum I can use live logging to get a result, even if it doesn’t show up on the tile or activity feed. Thanks @minollo , I appreciate your time.