diff --git a/devicetypes/smartthings/smartsense-multi.src/smartsense-multi.groovy b/devicetypes/smartthings/smartsense-multi.src/smartsense-multi.groovy index 17f5ddd..8ed1a3d 100644 --- a/devicetypes/smartthings/smartsense-multi.src/smartsense-multi.groovy +++ b/devicetypes/smartthings/smartsense-multi.src/smartsense-multi.groovy @@ -45,17 +45,28 @@ metadata { } 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 + section { + input 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: "Temperature Offset", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false + } + section { + input("garageSensor", "enum", title: "Do you want to use this sensor on a garage door?", options: ["Yes", "No"], defaultValue: "No", required: false, displayDuringSetup: false) + } } tiles(scale: 2) { - multiAttributeTile(name:"contact", type: "generic", width: 6, height: 4){ - tileAttribute ("device.contact", key: "PRIMARY_CONTROL") { - attributeState "open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e" + multiAttributeTile(name:"status", type: "generic", width: 6, height: 4){ + tileAttribute ("device.status", key: "PRIMARY_CONTROL") { attributeState "closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821" + attributeState "open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e" + attributeState "garage-closed", label:'Closed', icon:"st.doors.garage.garage-closed", backgroundColor:"#79b821" + attributeState "garage-open", label:'Open', icon:"st.doors.garage.garage-open", backgroundColor:"#ffa81e" } } + 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") + } standardTile("acceleration", "device.acceleration", width: 2, height: 2) { state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#53a7c0") @@ -78,8 +89,8 @@ metadata { state "battery", label:'${currentValue}% battery', unit:"" } - main(["contact", "acceleration", "temperature"]) - details(["contact", "acceleration", "temperature", "battery"]) + main(["status", "acceleration", "temperature"]) + details(["status", "acceleration", "temperature", "battery"]) } } @@ -87,7 +98,9 @@ def parse(String description) { def results if (!isSupportedDescription(description) || zigbee.isZoneType19(description)) { - results = parseSingleMessage(description) + if (garageSensor != "Yes") { + results = parseSingleMessage(description) + } } else if (description == 'updated') { //TODO is there a better way to handle this like the other device types? @@ -203,7 +216,9 @@ private List parseContactMessage(String description) { parts.each { part -> part = part.trim() if (part.startsWith('contactState:')) { - results.addAll(getContactResult(part, description)) + if (garageSensor != "Yes") { + results.addAll(getContactResult(part, description)) + } } else if (part.startsWith('accelerationState:')) { results << getAccelerationResult(part, description) @@ -225,6 +240,29 @@ private List parseContactMessage(String description) { results } +def updated() { + log.debug "updated called" + log.info "garage value : $garageSensor" + if (garageSensor == "Yes") { + def descriptionText = "Updating device to garage sensor" + if (device.latestValue("status") == "open") { + sendEvent(name: 'status', value: 'garage-open', descriptionText: descriptionText) + } + else if (device.latestValue("status") == "closed") { + sendEvent(name: 'status', value: 'garage-closed', descriptionText: descriptionText) + } + } + else { + def descriptionText = "Updating device to open/close sensor" + if (device.latestValue("status") == "garage-open") { + sendEvent(name: 'status', value: 'open', descriptionText: descriptionText) + } + else if (device.latestValue("status") == "garage-closed") { + sendEvent(name: 'status', value: 'closed', descriptionText: descriptionText) + } + } +} + private List parseOrientationMessage(String description) { def results = [] def xyzResults = [x: 0, y: 0, z: 0] @@ -254,7 +292,34 @@ private List parseOrientationMessage(String description) { } } - results << getXyzResult(xyzResults, description) + def xyz = getXyzResult(xyzResults, description) + results << xyz + + if (garageSensor == "Yes") { + // Looks for Z-axis orientation as virtual contact state + def a = xyz.value.split(',').collect{it.toInteger()} + def absValueXY = Math.max(Math.abs(a[0]), Math.abs(a[1])) + def absValueZ = Math.abs(a[2]) + log.debug "absValueXY: $absValueXY, absValueZ: $absValueZ" + + def contactValue = null + def garageValue = null + + if (absValueZ > 825 && absValueXY < 175) { + contactValue = 'open' + garageValue = 'garage-open' + log.debug "STATUS: open" + } + else if (absValueZ < 75 && absValueXY > 825) { + contactValue = 'closed' + garageValue = 'garage-closed' + log.debug "STATUS: closed" + } + def linkText = getLinkText(device) + def descriptionText = "${linkText} was ${contactValue == 'open' ? 'opened' : 'closed'}" + results << createEvent(name: "contact", value: contactValue, descriptionText: descriptionText, unit: "", displayed: false) + results << createEvent(name: "status", value: garageValue, descriptionText: descriptionText, unit: "") + } results }