From 968834e33ec97fdec787f9fb38bd07fa4171d495 Mon Sep 17 00:00:00 2001 From: Tom Manley Date: Mon, 18 Jan 2016 13:29:48 -0600 Subject: [PATCH] Use table for battery voltage to percent remaining calculation The new table based approach yields a more accurate battery percentage remaining than the old linear calculation. Resolves: https://smartthings.atlassian.net/browse/SMJN-39 --- .../arrival-sensor-ha.groovy | 44 ++++++++++-------- .../smartsense-moisture-sensor.groovy | 45 ++++++++++++++----- .../smartsense-motion-sensor.groovy | 38 +++++++++++----- .../smartsense-multi-sensor.groovy | 35 +++++++++++---- 4 files changed, 112 insertions(+), 50 deletions(-) diff --git a/devicetypes/smartthings/arrival-sensor-ha.src/arrival-sensor-ha.groovy b/devicetypes/smartthings/arrival-sensor-ha.src/arrival-sensor-ha.groovy index 62519f2..d2f1660 100644 --- a/devicetypes/smartthings/arrival-sensor-ha.src/arrival-sensor-ha.groovy +++ b/devicetypes/smartthings/arrival-sensor-ha.src/arrival-sensor-ha.groovy @@ -88,31 +88,37 @@ private handleReportAttributeMessage(String description) { } } -private handleBatteryEvent(rawValue) { - def linkText = getLinkText(device) - - def eventMap = [ - name: 'battery', - value: '--' - ] - - def volts = rawValue / 10 - if (volts > 0){ - def minVolts = 2.0 - def maxVolts = 2.8 +/** + * Create battery event from reported battery voltage. + * + * @param volts Battery voltage in .1V increments + */ +private handleBatteryEvent(volts) { + if (volts == 0 || volts == 255) { + log.debug "Ignoring invalid value for voltage (${volts/10}V)" + } + else { + def batteryMap = [28:100, 27:100, 26:100, 25:90, 24:90, 23:70, + 22:70, 21:50, 20:50, 19:30, 18:30, 17:15, 16:1, 15:0] + def minVolts = 15 + def maxVolts = 28 if (volts < minVolts) volts = minVolts else if (volts > maxVolts) volts = maxVolts - def pct = (volts - minVolts) / (maxVolts - minVolts) - - eventMap.value = Math.round(pct * 100) - eventMap.descriptionText = "${linkText} battery was ${eventMap.value}%" + def pct = batteryMap[volts] + if (pct != null) { + def linkText = getLinkText(device) + def eventMap = [ + name: 'battery', + value: pct, + descriptionText: "${linkText} battery was ${pct}%" + ] + log.debug "Creating battery event for voltage=${volts/10}V: ${eventMap}" + sendEvent(eventMap) + } } - - log.debug "Creating battery event: ${eventMap}" - sendEvent(eventMap) } private handlePresenceEvent(present) { diff --git a/devicetypes/smartthings/smartsense-moisture-sensor.src/smartsense-moisture-sensor.groovy b/devicetypes/smartthings/smartsense-moisture-sensor.src/smartsense-moisture-sensor.groovy index 64192df..1c38e23 100644 --- a/devicetypes/smartthings/smartsense-moisture-sensor.src/smartsense-moisture-sensor.groovy +++ b/devicetypes/smartthings/smartsense-moisture-sensor.src/smartsense-moisture-sensor.groovy @@ -215,24 +215,47 @@ def getTemperature(value) { } private Map getBatteryResult(rawValue) { - log.debug 'Battery' + log.debug "Battery rawValue = ${rawValue}" def linkText = getLinkText(device) def result = [ - name: 'battery' + name: 'battery', + value: '--' ] def volts = rawValue / 10 - def descriptionText - if (volts > 3.5) { - result.descriptionText = "${linkText} battery has too much power (${volts} volts)." - } + + if (rawValue == 0 || rawValue == 255) {} else { - def minVolts = 2.1 - def maxVolts = 3.0 - def pct = (volts - minVolts) / (maxVolts - minVolts) - result.value = Math.min(100, (int) pct * 100) - result.descriptionText = "${linkText} battery was ${result.value}%" + if (volts > 3.5) { + result.descriptionText = "${linkText} battery has too much power (${volts} volts)." + } + else { + if (device.getDataValue("manufacturer") == "SmartThings") { + volts = rawValue // For the batteryMap to work the key needs to be an int + def batteryMap = [28:100, 27:100, 26:100, 25:90, 24:90, 23:70, + 22:70, 21:50, 20:50, 19:30, 18:30, 17:15, 16:1, 15:0] + def minVolts = 15 + def maxVolts = 28 + + if (volts < minVolts) + volts = minVolts + else if (volts > maxVolts) + volts = maxVolts + def pct = batteryMap[volts] + if (pct != null) { + result.value = pct + result.descriptionText = "${linkText} battery was ${result.value}%" + } + } + else { + def minVolts = 2.1 + def maxVolts = 3.0 + def pct = (volts - minVolts) / (maxVolts - minVolts) + result.value = Math.min(100, (int) pct * 100) + result.descriptionText = "${linkText} battery was ${result.value}%" + } + } } return result diff --git a/devicetypes/smartthings/smartsense-motion-sensor.src/smartsense-motion-sensor.groovy b/devicetypes/smartthings/smartsense-motion-sensor.src/smartsense-motion-sensor.groovy index 6e0cc93..10b0740 100644 --- a/devicetypes/smartthings/smartsense-motion-sensor.src/smartsense-motion-sensor.groovy +++ b/devicetypes/smartthings/smartsense-motion-sensor.src/smartsense-motion-sensor.groovy @@ -230,30 +230,46 @@ def getTemperature(value) { } private Map getBatteryResult(rawValue) { - log.debug 'Battery' + log.debug "Battery rawValue = ${rawValue}" def linkText = getLinkText(device) - log.debug rawValue - def result = [ name: 'battery', value: '--' ] def volts = rawValue / 10 - def descriptionText - if (rawValue == 0) {} + if (rawValue == 0 || rawValue == 255) {} else { if (volts > 3.5) { result.descriptionText = "${linkText} battery has too much power (${volts} volts)." } - else if (volts > 0){ - def minVolts = 2.1 - def maxVolts = 3.0 - def pct = (volts - minVolts) / (maxVolts - minVolts) - result.value = Math.min(100, (int) pct * 100) - result.descriptionText = "${linkText} battery was ${result.value}%" + else { + if (device.getDataValue("manufacturer") == "SmartThings") { + volts = rawValue // For the batteryMap to work the key needs to be an int + def batteryMap = [28:100, 27:100, 26:100, 25:90, 24:90, 23:70, + 22:70, 21:50, 20:50, 19:30, 18:30, 17:15, 16:1, 15:0] + def minVolts = 15 + def maxVolts = 28 + + if (volts < minVolts) + volts = minVolts + else if (volts > maxVolts) + volts = maxVolts + def pct = batteryMap[volts] + if (pct != null) { + result.value = pct + result.descriptionText = "${linkText} battery was ${result.value}%" + } + } + else { + def minVolts = 2.1 + def maxVolts = 3.0 + def pct = (volts - minVolts) / (maxVolts - minVolts) + result.value = Math.min(100, (int) pct * 100) + result.descriptionText = "${linkText} battery was ${result.value}%" + } } } diff --git a/devicetypes/smartthings/smartsense-multi-sensor.src/smartsense-multi-sensor.groovy b/devicetypes/smartthings/smartsense-multi-sensor.src/smartsense-multi-sensor.groovy index ab66857..70cc9ee 100644 --- a/devicetypes/smartthings/smartsense-multi-sensor.src/smartsense-multi-sensor.groovy +++ b/devicetypes/smartthings/smartsense-multi-sensor.src/smartsense-multi-sensor.groovy @@ -303,8 +303,7 @@ def getTemperature(value) { } private Map getBatteryResult(rawValue) { - log.debug "Battery" - log.debug rawValue + log.debug "Battery rawValue = ${rawValue}" def linkText = getLinkText(device) def result = [ @@ -313,19 +312,37 @@ private Map getBatteryResult(rawValue) { ] def volts = rawValue / 10 - def descriptionText - if (rawValue == 255) {} + if (rawValue == 0 || rawValue == 255) {} else { if (volts > 3.5) { result.descriptionText = "${linkText} battery has too much power (${volts} volts)." } else { - def minVolts = 2.1 - def maxVolts = 3.0 - def pct = (volts - minVolts) / (maxVolts - minVolts) - result.value = Math.min(100, (int) pct * 100) - result.descriptionText = "${linkText} battery was ${result.value}%" + if (device.getDataValue("manufacturer") == "SmartThings") { + volts = rawValue // For the batteryMap to work the key needs to be an int + def batteryMap = [28:100, 27:100, 26:100, 25:90, 24:90, 23:70, + 22:70, 21:50, 20:50, 19:30, 18:30, 17:15, 16:1, 15:0] + def minVolts = 15 + def maxVolts = 28 + + if (volts < minVolts) + volts = minVolts + else if (volts > maxVolts) + volts = maxVolts + def pct = batteryMap[volts] + if (pct != null) { + result.value = pct + result.descriptionText = "${linkText} battery was ${result.value}%" + } + } + else { + def minVolts = 2.1 + def maxVolts = 3.0 + def pct = (volts - minVolts) / (maxVolts - minVolts) + result.value = Math.min(100, (int) pct * 100) + result.descriptionText = "${linkText} battery was ${result.value}%" + } } }