From c86d61a8626f24682228c0c085806a7b98c22a80 Mon Sep 17 00:00:00 2001 From: Zach Varberg Date: Wed, 26 Jul 2017 14:14:21 -0500 Subject: [PATCH] Smooth battery values for smartsense devices Since we have been receiving a lot of reports and complaints about the battery readings on the smartsense devices that received battery updates (multi and motion), we are adding this code to smooth out the readings so it doesn't constantly oscillate between two values. The basic logic is, only create an event if we have two readings in a row that are the same, or a reading is more than 100 millivolts off of the current battery percentage. --- .../smartsense-motion-sensor.groovy | 26 +++++++++++++++---- .../smartsense-multi-sensor.groovy | 26 +++++++++++++++---- 2 files changed, 42 insertions(+), 10 deletions(-) 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 c00e65e..7eb8118 100644 --- a/devicetypes/smartthings/smartsense-motion-sensor.src/smartsense-motion-sensor.groovy +++ b/devicetypes/smartthings/smartsense-motion-sensor.src/smartsense-motion-sensor.groovy @@ -173,11 +173,27 @@ private Map getBatteryResult(rawValue) { } else { def minVolts = 2.4 def maxVolts = 2.7 - def pct = (volts - minVolts) / (maxVolts - minVolts) - def roundedPct = Math.round(pct * 100) - if (roundedPct <= 0) - roundedPct = 1 - result.value = Math.min(100, roundedPct) + // Get the current battery percentage as a multiplier 0 - 1 + def curValVolts = Integer.parseInt(device.currentState("battery")?.value ?: "100") / 100.0 + // Find the corresponding voltage from our range + curValVolts = curValVolts * (maxVolts - minVolts) + minVolts + // Round to the nearest 10th of a volt + curValVolts = Math.round(10 * curValVolts) / 10.0 + // Only update the battery reading if we don't have a last reading, + // OR we have received the same reading twice in a row + // OR we don't currently have a battery reading + // OR the value we just received is at least 2 steps off from the last reported value + if(state?.lastVolts == null || state?.lastVolts == volts || device.currentState("battery")?.value == null || Math.abs(curValVolts - volts) > 0.1) { + def pct = (volts - minVolts) / (maxVolts - minVolts) + def roundedPct = Math.round(pct * 100) + if (roundedPct <= 0) + roundedPct = 1 + result.value = Math.min(100, roundedPct) + } else { + // Don't update as we want to smooth the battery values + result = null + } + state.lastVolts = volts } } 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 a8d436e..38331df 100644 --- a/devicetypes/smartthings/smartsense-multi-sensor.src/smartsense-multi-sensor.groovy +++ b/devicetypes/smartthings/smartsense-multi-sensor.src/smartsense-multi-sensor.groovy @@ -275,11 +275,27 @@ private Map getBatteryResult(rawValue) { } else { def minVolts = 2.1 def maxVolts = 2.7 - def pct = (volts - minVolts) / (maxVolts - minVolts) - def roundedPct = Math.round(pct * 100) - if (roundedPct <= 0) - roundedPct = 1 - result.value = Math.min(100, roundedPct) + // Get the current battery percentage as a multiplier 0 - 1 + def curValVolts = Integer.parseInt(device.currentState("battery")?.value ?: "100") / 100.0 + // Find the corresponding voltage from our range + curValVolts = curValVolts * (maxVolts - minVolts) + minVolts + // Round to the nearest 10th of a volt + curValVolts = Math.round(10 * curValVolts) / 10.0 + // Only update the battery reading if we don't have a last reading, + // OR we have received the same reading twice in a row + // OR we don't currently have a battery reading + // OR the value we just received is at least 2 steps off from the last reported value + if(state?.lastVolts == null || state?.lastVolts == volts || device.currentState("battery")?.value == null || Math.abs(curValVolts - volts) > 0.1) { + def pct = (volts - minVolts) / (maxVolts - minVolts) + def roundedPct = Math.round(pct * 100) + if (roundedPct <= 0) + roundedPct = 1 + result.value = Math.min(100, roundedPct) + } else { + // Don't update as we want to smooth the battery values + result = null + } + state.lastVolts = volts } }