"New" SmartThings 2018 sensors

I have made a mod to @jp0550's mod for this driver. This will be my interim driver till Hubitat/Samsung resolve the duplicate events that occur after these button devices have been unused for a period of time. Essentially it will ignore multiple button press events that occur with a specified timeframe. When I receive duplicates my logs show that they occur within 2 seconds of each other. I have found that 2500ms to be the sweet spot for me. Your mileage may vary and so I made this an adjustable option in the driver preferences.
Hopefully I won't need this driver for much longer.

And, yes, I know everyone does not experience this issue even with the same firmware. This driver is for those that do.

/*
 * 	12/30/18 Edited by Stephan Hackett
 *		- added option to ignore duplicate events received within adjustable timeframe (2500ms/2.5s worked for me). Tweak this preference to fit your scenario.
*/


metadata {
    definition ( name : "Smartthings Button", namespace: "stephack", author: "Robert Morris, Mitch Pond, jp0550, Stephan Hackett" ) {
    	capability "Holdable Button"
        capability "Battery"
        capability "Refresh"
        capability "Double Tapable Button"
        capability "Pushable Button"
        capability "Temperature Measurement"
        capability "Sensor"
        capability "Actuator"
        capability "Configuration"  
        
        fingerprint inClusters: "0000,0001,0003,0020,0402,0500", outClusters: "0003,0019", manufacturer: "Samjin", model: "button"
    }
}

preferences {
	input("debounce", "number", title: "Ignore multiple events received within this timeframe (ms):")
}

def parse(description){
 	log.debug "Received message: $description"    
    def event = zigbee.getEvent(description)
    
    if( description?.startsWith("catchall:") || description?.startsWith("read attr -") ){
        def descMap = zigbee.parseDescriptionAsMap(description)
        log.debug "Desc map: $descMap"
        if(descMap.clusterInt == 0x0001 && descMap.attrInt == 0x0020){ //battery
            event = getBatteryResult(zigbee.convertHexToInt(descMap.value))
        }
    }
    else if( description?.startsWith("zone status") ){
        event = parseIasButtonMessage(description)
    }
    
    log.debug "Parsed event $event"
    def result = event ? createEvent(event) : []
    
    if (description?.startsWith('enroll request')) {
		List cmds = zigbee.enrollResponse()
		log.debug "enroll response: ${cmds}"
		result = cmds?.collect { new hubitat.device.HubAction(it) }
	}
    
    result
}

def parseIasButtonMessage(description){
 	def zs = zigbee.parseZoneStatus(description)
    
    def eventType
    
    if(zs.isAlarm1Set()) eventType = "pushed"
    if(zs.isAlarm2Set()) eventType = "doubleTapped" 
    if(zs.isAlarm1Set() && zs.isAlarm2Set()) eventType = "held" 
    
    if(eventType){
		def rejectTime = 0
		if(debounce) rejectTime = debounce
		def recentEvents = device.eventsSince(new Date(now() - rejectTime)).findAll{it.name == eventType}
        log.info "Duplicate event rejected" 
        if(recentEvents.size == 0){
     		return [ name: eventType, value: 1, isStateChange: true, descriptionText: "Button 1 was $eventType" ]
		}
    }
}

def getBatteryResult(rawValue){
 	log.debug "Parse battery: $rawValue"
    def volts = rawValue / 10.0
    if(volts > 3.0 || volts == 0 || rawValue == 0xFF){
     	return [:]   
    }
    else {
        def result = [ name : 'battery' ]
        def minVolts = 2.1
        def maxVolts = 3.0
        def pct = (volts - minVolts) / (maxVolts - minVolts)
        result.value = Math.min(100, (int)(pct * 100))
        def linkText = getLinkText(device)
        result.descriptionText = "$linkText battery was ${result.value}%"
        return result
    }
}

def refresh(){
    zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x20) + zigbee.readAttribute(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0) + zigbee.enrollResponse()
}

def configure(){
    log.debug "Configure"
    
    sendEvent(name: 'numberOfButtons', value: 1)
    
    zigbee.onOffConfig() + 
        zigbee.levelConfig() + 
        zigbee.configureReporting(zigbee.POWER_CONFIGURATION_CLUSTER, 0x20, DataType.UINT8, 30, 21600, 0x01) + 
        zigbee.temperatureConfig(30, 3600) +
        zigbee.enrollResponse() + 
        zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x20) + 
        zigbee.readAttribute(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0) + []
}
3 Likes