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 8248bf0..4e9a32c 100644 --- a/devicetypes/smartthings/smartsense-moisture-sensor.src/smartsense-moisture-sensor.groovy +++ b/devicetypes/smartthings/smartsense-moisture-sensor.src/smartsense-moisture-sensor.groovy @@ -255,7 +255,8 @@ private Map getBatteryResult(rawValue) { def minVolts = 2.1 def maxVolts = 3.0 def pct = (volts - minVolts) / (maxVolts - minVolts) - result.value = Math.min(100, (int) pct * 100) + def roundedPct = Math.round(pct * 100) + result.value = Math.min(100, roundedPct) result.descriptionText = "{{ device.displayName }} battery was {{ value }}%" } } 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 660b0b7..5d80f07 100644 --- a/devicetypes/smartthings/smartsense-motion-sensor.src/smartsense-motion-sensor.groovy +++ b/devicetypes/smartthings/smartsense-motion-sensor.src/smartsense-motion-sensor.groovy @@ -271,7 +271,8 @@ private Map getBatteryResult(rawValue) { def minVolts = 2.1 def maxVolts = 3.0 def pct = (volts - minVolts) / (maxVolts - minVolts) - result.value = Math.min(100, (int) pct * 100) + def roundedPct = Math.round(pct * 100) + result.value = Math.min(100, roundedPct) result.descriptionText = "{{ device.displayName }} battery was {{ value }}%" } } diff --git a/devicetypes/smartthings/smartsense-motion-temp-sensor.src/smartsense-motion-temp-sensor.groovy b/devicetypes/smartthings/smartsense-motion-temp-sensor.src/smartsense-motion-temp-sensor.groovy index 48b3945..446ec70 100644 --- a/devicetypes/smartthings/smartsense-motion-temp-sensor.src/smartsense-motion-temp-sensor.groovy +++ b/devicetypes/smartthings/smartsense-motion-temp-sensor.src/smartsense-motion-temp-sensor.groovy @@ -24,7 +24,7 @@ metadata { capability "Temperature Measurement" capability "Refresh" capability "Sensor" - + command "enrollResponse" } @@ -73,7 +73,7 @@ metadata { def parse(String description) { log.debug "description: $description" - + Map map = [:] if (description?.startsWith('catchall:')) { map = parseCatchAllMessage(description) @@ -87,10 +87,10 @@ def parse(String description) { else if (description?.startsWith('zone status')) { map = parseIasMessage(description) } - + log.debug "Parse returned $map" def result = map ? createEvent(map) : null - + if (description?.startsWith('enroll request')) { List cmds = enrollResponse() log.debug "enroll response: ${cmds}" @@ -128,7 +128,7 @@ private Map parseCatchAllMessage(String description) { private boolean shouldProcessMessage(cluster) { // 0x0B is default response indicating message got through // 0x07 is bind message - boolean ignoredMessage = cluster.profileId != 0x0104 || + boolean ignoredMessage = cluster.profileId != 0x0104 || cluster.command == 0x0B || cluster.command == 0x07 || (cluster.data.size() > 0 && cluster.data.first() == 0x3e) @@ -141,7 +141,7 @@ private Map parseReportAttributeMessage(String description) { map += [(nameAndValue[0].trim()):nameAndValue[1].trim()] } log.debug "Desc Map: $descMap" - + Map resultMap = [:] if (descMap.cluster == "0402" && descMap.attrId == "0000") { def value = getTemperature(descMap.value) @@ -153,11 +153,11 @@ private Map parseReportAttributeMessage(String description) { else if (descMap.cluster == "0406" && descMap.attrId == "0000") { def value = descMap.value.endsWith("01") ? "active" : "inactive" resultMap = getMotionResult(value) - } - + } + return resultMap } - + private Map parseCustomMessage(String description) { Map resultMap = [:] if (description?.startsWith('temperature: ')) { @@ -170,7 +170,7 @@ private Map parseCustomMessage(String description) { private Map parseIasMessage(String description) { List parsedMsg = description.split(' ') String msgCode = parsedMsg[2] - + Map resultMap = [:] switch(msgCode) { case '0x0020': // Closed/No Motion/Dry @@ -240,7 +240,8 @@ private Map getBatteryResult(rawValue) { def minVolts = 2.1 def maxVolts = 3.0 def pct = (volts - minVolts) / (maxVolts - minVolts) - result.value = Math.min(100, (int) pct * 100) + def roundedPct = Math.round(pct * 100) + result.value = Math.min(100, roundedPct) 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 d13dffb..02861cc 100644 --- a/devicetypes/smartthings/smartsense-multi-sensor.src/smartsense-multi-sensor.groovy +++ b/devicetypes/smartthings/smartsense-multi-sensor.src/smartsense-multi-sensor.groovy @@ -338,7 +338,8 @@ private Map getBatteryResult(rawValue) { def minVolts = 2.1 def maxVolts = 3.0 def pct = (volts - minVolts) / (maxVolts - minVolts) - result.value = Math.min(100, (int) pct * 100) + def roundedPct = Math.round(pct * 100) + result.value = Math.min(100, roundedPct) result.descriptionText = "{{ device.displayName }} battery was {{ value }}%" } } diff --git a/devicetypes/smartthings/smartsense-open-closed-accelerometer-sensor.src/smartsense-open-closed-accelerometer-sensor.groovy b/devicetypes/smartthings/smartsense-open-closed-accelerometer-sensor.src/smartsense-open-closed-accelerometer-sensor.groovy index 9f03f17..d12124a 100644 --- a/devicetypes/smartthings/smartsense-open-closed-accelerometer-sensor.src/smartsense-open-closed-accelerometer-sensor.groovy +++ b/devicetypes/smartthings/smartsense-open-closed-accelerometer-sensor.src/smartsense-open-closed-accelerometer-sensor.groovy @@ -234,7 +234,8 @@ def getTemperature(value) { def minVolts = 2.1 def maxVolts = 3.0 def pct = (volts - minVolts) / (maxVolts - minVolts) - result.value = Math.min(100, (int) pct * 100) + def roundedPct = Math.round(pct * 100) + result.value = Math.min(100, roundedPct) result.descriptionText = "${linkText} battery was ${result.value}%" } diff --git a/devicetypes/smartthings/smartsense-open-closed-sensor.src/smartsense-open-closed-sensor.groovy b/devicetypes/smartthings/smartsense-open-closed-sensor.src/smartsense-open-closed-sensor.groovy index 47d930d..aaf14fb 100644 --- a/devicetypes/smartthings/smartsense-open-closed-sensor.src/smartsense-open-closed-sensor.groovy +++ b/devicetypes/smartthings/smartsense-open-closed-sensor.src/smartsense-open-closed-sensor.groovy @@ -13,7 +13,7 @@ * for the specific language governing permissions and limitations under the License. * */ - + metadata { definition (name: "SmartSense Open/Closed Sensor", namespace: "smartthings", author: "SmartThings", category: "C2") { capability "Battery" @@ -22,24 +22,24 @@ metadata { capability "Refresh" capability "Temperature Measurement" capability "Health Check" - + command "enrollResponse" - - + + fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3300-S" fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3300" fingerprint inClusters: "0000,0001,0003,0020,0402,0500,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3320-L", deviceJoinName: "Iris Contact Sensor" } - + simulator { - + } preferences { input title: "Temperature Offset", description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter \"-5\". If 3 degrees too cold, enter \"+3\".", displayDuringSetup: false, type: "paragraph", element: "paragraph" input "tempOffset", "number", title: "Degrees", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false } - + tiles(scale: 2) { multiAttributeTile(name:"contact", type: "generic", width: 6, height: 4){ tileAttribute ("device.contact", key: "PRIMARY_CONTROL") { @@ -72,10 +72,10 @@ metadata { details(["contact","temperature","battery","refresh"]) } } - + def parse(String description) { log.debug "description: $description" - + Map map = [:] if (description?.startsWith('catchall:')) { map = parseCatchAllMessage(description) @@ -89,10 +89,10 @@ def parse(String description) { else if (description?.startsWith('zone status')) { map = parseIasMessage(description) } - + log.debug "Parse returned $map" def result = map ? createEvent(map) : null - + if (description?.startsWith('enroll request')) { List cmds = enrollResponse() log.debug "enroll response: ${cmds}" @@ -100,7 +100,7 @@ def parse(String description) { } return result } - + private Map parseCatchAllMessage(String description) { Map resultMap = [:] def cluster = zigbee.parse(description) @@ -126,7 +126,7 @@ private Map parseCatchAllMessage(String description) { private boolean shouldProcessMessage(cluster) { // 0x0B is default response indicating message got through // 0x07 is bind message - boolean ignoredMessage = cluster.profileId != 0x0104 || + boolean ignoredMessage = cluster.profileId != 0x0104 || cluster.command == 0x0B || cluster.command == 0x07 || (cluster.data.size() > 0 && cluster.data.first() == 0x3e) @@ -136,14 +136,14 @@ private boolean shouldProcessMessage(cluster) { private int getHumidity(value) { return Math.round(Double.parseDouble(value)) } - + private Map parseReportAttributeMessage(String description) { Map descMap = (description - "read attr - ").split(",").inject([:]) { map, param -> def nameAndValue = param.split(":") map += [(nameAndValue[0].trim()):nameAndValue[1].trim()] } log.debug "Desc Map: $descMap" - + Map resultMap = [:] if (descMap.cluster == "0402" && descMap.attrId == "0000") { def value = getTemperature(descMap.value) @@ -152,10 +152,10 @@ private Map parseReportAttributeMessage(String description) { else if (descMap.cluster == "0001" && descMap.attrId == "0020") { resultMap = getBatteryResult(Integer.parseInt(descMap.value, 16)) } - + return resultMap } - + private Map parseCustomMessage(String description) { Map resultMap = [:] if (description?.startsWith('temperature: ')) { @@ -168,7 +168,7 @@ private Map parseCustomMessage(String description) { private Map parseIasMessage(String description) { List parsedMsg = description.split(' ') String msgCode = parsedMsg[2] - + Map resultMap = [:] switch(msgCode) { case '0x0020': // Closed/No Motion/Dry @@ -201,7 +201,7 @@ private Map parseIasMessage(String description) { } return resultMap } - + def getTemperature(value) { def celsius = Integer.parseInt(value, 16).shortValue() / 100 if(getTemperatureScale() == "C"){ @@ -214,11 +214,11 @@ def getTemperature(value) { private Map getBatteryResult(rawValue) { log.debug 'Battery' def linkText = getLinkText(device) - + def result = [ name: 'battery' ] - + def volts = rawValue / 10 def descriptionText if (rawValue == 0 || rawValue == 255) {} @@ -229,7 +229,8 @@ private Map getBatteryResult(rawValue) { def minVolts = 2.1 def maxVolts = 3.0 def pct = (volts - minVolts) / (maxVolts - minVolts) - result.value = Math.min(100, (int) pct * 100) + def roundedPct = Math.round(pct * 100) + result.value = Math.min(100, roundedPct) result.descriptionText = "${linkText} battery was ${result.value}%" } @@ -275,7 +276,7 @@ def refresh() { def configure() { sendEvent(name: "checkInterval", value: 7200, displayed: false) - + String zigbeeEui = swapEndianHex(device.hub.zigbeeEui) log.debug "Configuring Reporting, IAS CIE, and Bindings." def configCmds = [ diff --git a/devicetypes/smartthings/smartsense-temp-humidity-sensor.src/smartsense-temp-humidity-sensor.groovy b/devicetypes/smartthings/smartsense-temp-humidity-sensor.src/smartsense-temp-humidity-sensor.groovy index 0479b5d..0476f72 100644 --- a/devicetypes/smartthings/smartsense-temp-humidity-sensor.src/smartsense-temp-humidity-sensor.groovy +++ b/devicetypes/smartthings/smartsense-temp-humidity-sensor.src/smartsense-temp-humidity-sensor.groovy @@ -205,7 +205,8 @@ private Map getBatteryResult(rawValue) { def minVolts = 2.1 def maxVolts = 3.0 def pct = (volts - minVolts) / (maxVolts - minVolts) - result.value = Math.min(100, (int) pct * 100) + def roundedPct = Math.round(pct * 100) + result.value = Math.min(100, roundedPct) result.descriptionText = "${linkText} battery was ${result.value}%" } diff --git a/devicetypes/smartthings/tyco-door-window-sensor.src/tyco-door-window-sensor.groovy b/devicetypes/smartthings/tyco-door-window-sensor.src/tyco-door-window-sensor.groovy index d9e650d..627ab1d 100644 --- a/devicetypes/smartthings/tyco-door-window-sensor.src/tyco-door-window-sensor.groovy +++ b/devicetypes/smartthings/tyco-door-window-sensor.src/tyco-door-window-sensor.groovy @@ -13,7 +13,7 @@ * for the specific language governing permissions and limitations under the License. * */ - + metadata { definition (name: "Tyco Door/Window Sensor", namespace: "smartthings", author: "SmartThings") { capability "Battery" @@ -21,28 +21,28 @@ metadata { capability "Contact Sensor" capability "Refresh" capability "Temperature Measurement" - + command "enrollResponse" - - + + fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "Visonic", model: "MCT-340 SMA" } - + simulator { - + } preferences { input title: "Temperature Offset", description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter \"-5\". If 3 degrees too cold, enter \"+3\".", displayDuringSetup: false, type: "paragraph", element: "paragraph" input "tempOffset", "number", title: "Degrees", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false } - + tiles { standardTile("contact", "device.contact", width: 2, height: 2) { state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e") state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821") } - + valueTile("temperature", "device.temperature", inactiveLabel: false) { state "temperature", label:'${currentValue}°', backgroundColors:[ @@ -58,23 +58,23 @@ metadata { valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false) { state "battery", label:'${currentValue}% battery', unit:"" } - + standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat") { state "default", action:"refresh.refresh", icon:"st.secondary.refresh" } - + standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat") { state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure" } - + main (["contact", "temperature"]) details(["contact","temperature","battery","refresh","configure"]) } } - + def parse(String description) { log.debug "description: $description" - + Map map = [:] if (description?.startsWith('catchall:')) { map = parseCatchAllMessage(description) @@ -88,10 +88,10 @@ def parse(String description) { else if (description?.startsWith('zone status')) { map = parseIasMessage(description) } - + log.debug "Parse returned $map" def result = map ? createEvent(map) : null - + if (description?.startsWith('enroll request')) { List cmds = enrollResponse() log.debug "enroll response: ${cmds}" @@ -99,7 +99,7 @@ def parse(String description) { } return result } - + private Map parseCatchAllMessage(String description) { Map resultMap = [:] def cluster = zigbee.parse(description) @@ -125,20 +125,20 @@ private Map parseCatchAllMessage(String description) { private boolean shouldProcessMessage(cluster) { // 0x0B is default response indicating message got through // 0x07 is bind message - boolean ignoredMessage = cluster.profileId != 0x0104 || + boolean ignoredMessage = cluster.profileId != 0x0104 || cluster.command == 0x0B || cluster.command == 0x07 || (cluster.data.size() > 0 && cluster.data.first() == 0x3e) return !ignoredMessage } - + private Map parseReportAttributeMessage(String description) { Map descMap = (description - "read attr - ").split(",").inject([:]) { map, param -> def nameAndValue = param.split(":") map += [(nameAndValue[0].trim()):nameAndValue[1].trim()] } log.debug "Desc Map: $descMap" - + Map resultMap = [:] if (descMap.cluster == "0402" && descMap.attrId == "0000") { def value = getTemperature(descMap.value) @@ -147,10 +147,10 @@ private Map parseReportAttributeMessage(String description) { else if (descMap.cluster == "0001" && descMap.attrId == "0020") { resultMap = getBatteryResult(Integer.parseInt(descMap.value, 16)) } - + return resultMap } - + private Map parseCustomMessage(String description) { Map resultMap = [:] if (description?.startsWith('temperature: ')) { @@ -163,7 +163,7 @@ private Map parseCustomMessage(String description) { private Map parseIasMessage(String description) { List parsedMsg = description.split(' ') String msgCode = parsedMsg[2] - + Map resultMap = [:] switch(msgCode) { case '0x0020': // Closed/No Motion/Dry @@ -196,7 +196,7 @@ private Map parseIasMessage(String description) { } return resultMap } - + def getTemperature(value) { def celsius = Integer.parseInt(value, 16).shortValue() / 100 if(getTemperatureScale() == "C"){ @@ -209,11 +209,11 @@ def getTemperature(value) { private Map getBatteryResult(rawValue) { log.debug 'Battery' def linkText = getLinkText(device) - + def result = [ name: 'battery' ] - + def volts = rawValue / 10 def descriptionText if (volts > 3.5) { @@ -223,7 +223,8 @@ private Map getBatteryResult(rawValue) { def minVolts = 2.1 def maxVolts = 3.0 def pct = (volts - minVolts) / (maxVolts - minVolts) - result.value = Math.min(100, (int) pct * 100) + def roundedPct = Math.round(pct * 100) + result.value = Math.min(100, roundedPct) result.descriptionText = "${linkText} battery was ${result.value}%" } @@ -261,7 +262,7 @@ def refresh() { log.debug "Refreshing Temperature and Battery" [ - + "st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 200", "st rattr 0x${device.deviceNetworkId} 1 1 0x20" @@ -274,24 +275,24 @@ def configure() { log.debug "Configuring Reporting, IAS CIE, and Bindings." def configCmds = [ "delay 1000", - + "zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200", "send 0x${device.deviceNetworkId} 1 1", "delay 1500", - + "zcl global send-me-a-report 1 0x20 0x20 600 3600 {01}", "delay 200", "send 0x${device.deviceNetworkId} 1 1", "delay 1500", - + "zcl global send-me-a-report 0x402 0 0x29 300 3600 {6400}", "delay 200", "send 0x${device.deviceNetworkId} 1 1", "delay 1500", - - + + //"raw 0x500 {01 23 00 00 00}", "delay 200", //"send 0x${device.deviceNetworkId} 1 1", "delay 1500", - - + + "zdo bind 0x${device.deviceNetworkId} 1 1 0x402 {${device.zigbeeId}} {}", "delay 500", "zdo bind 0x${device.deviceNetworkId} 1 1 1 {${device.zigbeeId}} {}", - + "delay 500" ] return configCmds + enrollResponse() + refresh() // send refresh cmds as part of config @@ -299,11 +300,11 @@ def configure() { def enrollResponse() { log.debug "Sending enroll response" - [ - + [ + "raw 0x500 {01 23 00 00 00}", "delay 200", "send 0x${device.deviceNetworkId} 1 1" - + ] } private hex(value) {