New app — which CUSTOM DTH’s will work?

@eric182 As expected, I have inserted in metadata following code:
ocfDeviceType: “oic.d.light”, mnmn: “SmartThings”, vid: “generic-rgbw-color-bulb”
and it worked. Now it shows RGBW strip correctly in new app

1 Like

@milandjurovic71

If you don’t mind me asking, where exactly do you add those changes to the code?

I see the word metadata in the code, but I’m not as proficient as you when it comes to editing code. Thanks.

EDIT: I got this working with the changes you’ve recommended. Thank you for your help. Only problem is you don’t get color loop, blink or pulse…

Does making these “mnmn” and “vid” code modifications render the DTH useless in the classic app or will those devices then work in both the classic app and new?

Works in both

4 Likes

Has anyone had any success with the Ecobee Handler from @yvesracine in the new app?

Hi,

In order to see the basic attributes in the new Samsung app, you have to follow the instructions indicated in the zip file provided with the latest versions since 5.9.9.9.y.8:

For Android users, this sometimes means to use the IDE to force the cache refresh… Read the instructions for more details.

Regards.

Hi Yves,

THanks for the reply. I do not see a zip attached to my email.

" You can download the new versions at my store using your original sellfy download link"

I am one of your earliest contributors and I don’t have a download link (that I know of). I always used to get my updates attached to an email.

Let me know if I am missing something.

Thanks,

Rey

I am trying to make the Momentary Button Tile to work in the new Samsung app. I added the “vid:generic-switch” but it does not seem to have any effect. Any ideas?

metadata {
	definition (name: "Momentary Button Tile", namespace: "smartthings", author: "SmartThings", vid: "generic-switch") {
		capability "Actuator"
		capability "Switch"
		capability "Momentary"
		capability "Sensor"
	}

Why wouldn’t you use generic-button?

tried that as well. It didn’t work either.

Try to add this to:
ocfDeviceType: “oic.r.button”
and change vid to generic.button

Some time ago Smartthings staff announced that they are bringing ocfDeviceType: https://www.google.com/url?sa=t&source=web&rct=j&url=https://community.smartthings.com/t/new-device-metadata-for-ocf-standard/82833&ved=2ahUKEwjEsIj0qLPdAhUm5YMKHXJ_BZYQFjAAegQIBhAB&usg=AOvVaw2I2roKXY_i_nqU04iKAZ18
I have found this document that list some of this types: https://www.google.com/url?sa=t&source=web&rct=j&url=https://openconnectivity.org/specs/OCF_SmartHome_Device_Specification_v1.0.0.pdf&ved=2ahUKEwjEsIj0qLPdAhUm5YMKHXJ_BZYQFjABegQIAhAB&usg=AOvVaw0jYHpAV9FETtN6zCP5fYiO

I just hope by the time I have to use the new app, all my stuff will work. Haven’t looked into it a all really, but I do have a few device handlers that I manually copied from RAW. I hope those will still work. We also use our phones as presence sensors.

For the device handlers we are using alternative ones to the generic get fan switch, so we could just switch back.

did you go to the device page in the IDE and click update and save? or try flipping the assigned handler back and forth?

Aeon multisensor 6.

I’m currently using an edited version of Eric Maycock’s DTH in the classic app which provides me the required 1 minute updates of lux.

I’m hoping, when the time comes, that this will work in the new app.

Yes. Save and Publish (several times). Refreshed app. Force closed app and restarted app.

That didn’t seemed to work out either.

I got the Nexia Doorbell to work in the new app, notifies and notifications work with “notify me with” app.

I didn’t add Health Check though, what is that and how do I do that?

/**
 *  Nexia Doorbell Sensor - DB100Z
 *
 *  Copyright 2016 DarwinsDen.com
 *
 *  For installation instructions, DB100Z device review information, documentation and images,
 *  or for questions or to provide feedback on this device handler, please visit: 
 *
 *      darwinsden.com/db100z
 *
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 *  in compliance with the License. You may obtain a copy of the License at:
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
 *  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
 *  for the specific language governing permissions and limitations under the License.
 *
 *	Author: Darwin@DarwinsDen.com
 *	Date: 2016-03-26
 *
 *	Changelog:
 *
 *  1.4 (05/10/2018) -  Added contact sensor as capability for use with smart home monitor
 *  1.3 (09/25/2016) -  Added display of firmware version and updated to get battery level on initial installation
 *  1.2 (09/11/2016) -  Added preference option for push-to-break button (vs. default push-to-make) doorbell circuit. Note: enabling
 *                      this setting will also result in a doorbell notification if power is lost to the doorbell transformer.
 *  1.1 (05/11/2016) -  Added Button capability option.
 *	1.0 (03/26/2016) -	Initial 1.0 Release.
 *
 */
 
metadata {
	definition (name: "Nexia Doorbell Sensor", namespace: "darwinsden", author: "Darwin", mnmn:"SmartThings", vid: "generic-switch") {
		capability "Actuator"
		capability "Switch"
        capability "Momentary"
        capability "Button"
        capability "Contact Sensor"
		capability "Sensor"
		capability "Battery"
		capability "Refresh"
        capability "Configuration"
		
        attribute "status", "enum", ["off", "doorbell"]
        
		fingerprint deviceId: "0x0701", inClusters: "0x5E, 0x86, 0x72, 0x5A, 0x73, 0x80, 0x70, 0x71, 0x85, 0x59, 0x84, 0x7A"
	}

	simulator {
	}

    preferences {
        input "pushToBreak", "bool", title: "Doorbell circuit is push-to-break instead of push-to-make",  defaultValue: false,  displayDuringSetup: true, required: false	
    }
    
	tiles(scale: 2) {
    	multiAttributeTile(name:"status", type: "generic", width: 6, height: 4){
				tileAttribute ("device.status", key: "PRIMARY_CONTROL") {
					attributeState "off", label: "Off", icon:"st.Home.home30", backgroundColor:"#ffffff"
					attributeState "doorbell", label: "Ringing", icon:"st.alarm.alarm.alarm", backgroundColor:"#53a7c0"
				}
        }

		valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) {
			state "default", label:'${currentValue}% battery', unit:""
		}

		standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
			state "default", action:"refresh.refresh", icon:"st.secondary.refresh"
		}
        
        valueTile("firmwareVersion", "device.firmwareVersion", width:2, height: 2, decoration: "flat", inactiveLabel: false) {
			state "default", label: '${currentValue}'
		}
  

		main "status"
		details(["status", "battery", "refresh", "firmwareVersion"])
	}
}

def refresh() {
	   sendEvent(name: "status", value: "off", displayed: false, isStateChange: true)
	   sendEvent(name: "switch", value: "off", displayed: false, isStateChange: true)
       updated()
       configure()
 }

def configure() {
   log.debug ("configure() called")
   def commands = []
   commands << zwave.versionV1.versionGet().format()
   commands << zwave.batteryV1.batteryGet().format()
   delayBetween(commands,500)
}

def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd) {
    def event = createEvent(descriptionText: "${device.displayName} woke up", displayed: false)
    def result = []
    
    // Request battery info on wake up if levels have not been received within last 24 hours
	if (!state.lastBatteryReport || (new Date().time) - state.lastBatteryReport > 24*60*60*1000) {
       result += response(zwave.batteryV1.batteryGet().format())
       result += response("delay 1200")
    }
    result += response(zwave.wakeUpV1.wakeUpNoMoreInformation().format()) 
    return result
}

def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) {	
    //updateDataValue("applicationVersion", "${cmd.applicationVersion}")
    log.debug ("received Version Report")
    log.debug "applicationVersion:      ${cmd.applicationVersion}"
    log.debug "applicationSubVersion:   ${cmd.applicationSubVersion}"
    state.firmwareVersion=cmd.applicationVersion+'.'+cmd.applicationSubVersion
    log.debug "zWaveLibraryType:        ${cmd.zWaveLibraryType}"
    log.debug "zWaveProtocolVersion:    ${cmd.zWaveProtocolVersion}"
    log.debug "zWaveProtocolSubVersion: ${cmd.zWaveProtocolSubVersion}"
    setFirmwareVersion()
    createEvent([descriptionText: "Firmware V"+state.firmwareVersion, isStateChange: false])
}


// Unexpected command received
def zwaveEvent (physicalgraph.zwave.Command cmd) {
	   log.debug("Unhandled Command: $cmd")
	   return createEvent(descriptionText: cmd.toString(), isStateChange: false)
}

def switchOffVerification() {
       if (state.bellIsRinging) {
            log.debug("${device.displayName} switchOffVerification setting switch off")
            sendEvent(name: "status", value: "off", descriptionText: "Button released via verification check", isStateChange: true)
       }
       state.bellIsRinging = false
       sendEvent(name: "status", value: "off", displayed: false, isStateChange: true)
	   sendEvent(name: "switch", value: "off", displayed: false, isStateChange: true)
       sendEvent(name: "contact", value: "closed", displayed: false, isStateChange: true)      
}

//Battery Level received
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
       def result = null
       state.lastBatteryReport = new Date().time
       def batteryLevel = cmd.batteryLevel
       log.info("Battery: $batteryLevel")
       result = createEvent(name: "battery", value: batteryLevel, unit: "%", descriptionText: "Battery%: $batteryLevel", isStateChange: true)   
       return result
}

//Notification received
def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd) {
       def result = []
    
       // if the bell is not already ringing, record as a button press. We can't always trust an event of 1 to be a 
       // button press if messages arrive out of order or are missed
    
       if (!state.bellIsRinging) { 
           if (!pushToBreak | cmd.event == 0) //Event 1 will never be a doorbell trigger for a push to break circuit
           {
             // bell is not ringing - signal a button press
             state.bellIsRinging = true 
             log.debug("${device.displayName} notification event = $cmd.event triggered switch on")
             runIn(10, switchOffVerification) //set to turn off switch in 10 seconds in case the button release event is missed   
	         result += createEvent(name: "status", value: "doorbell", descriptionText: "Button pressed", isStateChange: true)
	         result += createEvent(name: "switch", value: "on", displayed: false, isStateChange: true)
             result += createEvent(name: "momentary", value: "pushed", displayed: false, isStateChange: true)
             result += createEvent(name: "button", value: "pushed", data: [buttonNumber: "1"], displayed: false, isStateChange: true)
             result += createEvent(name: "contact", value: "open", displayed: false, isStateChange: true)             
           }
       } else {
           // bell is ringing - signal a button release
           state.bellIsRinging = false
           log.debug("${device.displayName} notification event = $cmd.event triggered switch off")
           result += createEvent(name: "status", value: "off", descriptionText: "Button released", isStateChange: true)
	       result += createEvent(name: "switch", value: "off", displayed: false, isStateChange: true)
           result += createEvent(name: "contact", value: "closed", displayed: false, isStateChange: true)             
       } 
       return result
}

def setFirmwareVersion() {
   def versionInfo = ''
   if (state.firmwareVersion)
   {
      versionInfo=versionInfo+"Firmware V"+state.firmwareVersion
   }
   else 
   {
     versionInfo=versionInfo+"Firmware unknown"
   }   
   sendEvent(name: "firmwareVersion",  value: versionInfo, isStateChange: true)
}

def parse(description) {
	  def result = null
      log.debug (description)
	  if (description.startsWith("Err")) {
		   result = createEvent(descriptionText: description, isStateChange: true)
	  } else if (description != "updated") {
          def cmd = zwave.parse(description, [0x71: 3, 0x80: 1])
		  if (cmd) {
		      result = zwaveEvent(cmd)
		  } else {
			  log.debug("Couldn't zwave.parse '$description'")
		  }
	  }
	  return result
}

def updated() 
{
   log.debug ("updating")
   if (pushToBreak)
   {
      state.pushToBreak = true
   }
   else
   {
      state.pushToBreak = false
   } 
}   

Seems like just add…

capability “Health Check”

but what should be in the ping?

I found this…

def ping() {
return zigbee.onOffRefresh() or zwave.switchMultilevelV2.switchMultilevelGet().format() or whatever makes sense for the device
}

I wonder if that is accurate… Also, not sure if the default ping value should be set somewhere, or how to do that.

For DH, check out how it is setup for z-wave devices in the SmartThings public GitHub. (I think the Nexia doorbell is z-wave?)

Alright, so I cleaned up the code and added what I think is a good Health Check. I tested in New App and all seems fine with the Nexia Doorbell.

/**
 *  Nexia Doorbell Sensor - DB100Z
 *
 *  Copyright 2016 DarwinsDen.com
 *
 *  For installation instructions, DB100Z device review information, documentation and images,
 *  or for questions or to provide feedback on this device handler, please visit: 
 *
 *      darwinsden.com/db100z
 *
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 *  in compliance with the License. You may obtain a copy of the License at:
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
 *  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
 *  for the specific language governing permissions and limitations under the License.
 *
 *	Author: Darwin@DarwinsDen.com
 *	Date: 2016-03-26
 *
 *	Changelog:
 *
 *  1.4 (05/10/2018) -  Added contact sensor as capability for use with smart home monitor
 *  1.3 (09/25/2016) -  Added display of firmware version and updated to get battery level on initial installation
 *  1.2 (09/11/2016) -  Added preference option for push-to-break button (vs. default push-to-make) doorbell circuit. Note: enabling
 *                      this setting will also result in a doorbell notification if power is lost to the doorbell transformer.
 *  1.1 (05/11/2016) -  Added Button capability option.
 *	1.0 (03/26/2016) -	Initial 1.0 Release.
 *
 */
 
metadata {
	definition (name: "Nexia Doorbell Sensor", namespace: "darwinsden", author: "Darwin", mnmn:"SmartThings", vid: "generic-switch") {
		capability "Actuator"
		capability "Switch"
        capability "Momentary"
        capability "Button"
        capability "Contact Sensor"
		capability "Sensor"
		capability "Battery"
		capability "Refresh"
        capability "Configuration"
        capability "Health Check"
		
		attribute "status", "enum", ["off", "doorbell"]
        fingerprint deviceId: "0x0701", inClusters: "0x5E, 0x86, 0x72, 0x5A, 0x73, 0x80, 0x70, 0x71, 0x85, 0x59, 0x84, 0x7A"
	}

	simulator {
	}

    preferences {
		input "pushToBreak", "bool", title: "Doorbell circuit is push-to-break instead of push-to-make",  defaultValue: false,  displayDuringSetup: true, required: false	
    }
    
	tiles(scale: 2) {
    	multiAttributeTile(name:"status", type: "generic", width: 6, height: 4) {
			tileAttribute ("device.status", key: "PRIMARY_CONTROL") {
				attributeState "off", label: "Off", icon:"st.Home.home30", backgroundColor:"#ffffff"
				attributeState "doorbell", label: "Ringing", icon:"st.alarm.alarm.alarm", backgroundColor:"#53a7c0"
			}
        }

		valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) {
			state "default", label:'${currentValue}% battery', unit:""
		}

		standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
			state "default", action:"refresh.refresh", icon:"st.secondary.refresh"
		}
        
        valueTile("firmwareVersion", "device.firmwareVersion", width:2, height: 2, decoration: "flat", inactiveLabel: false) {
			state "default", label: '${currentValue}'
		}

		main "status"
		details(["status", "battery", "refresh", "firmwareVersion"])
	}
}

def installed() {
	refresh()
}

def ping() {
	refresh()
}

def refresh() {
	sendEvent(name: "status", value: "off", displayed: false, isStateChange: true)
	sendEvent(name: "switch", value: "off", displayed: false, isStateChange: true)
	updated()
	configure()
}

def updated() {
	// Device-Watch simply pings if no device events received for checkInterval duration of 32min = 2 * 15min + 2min lag time
	sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"])
    
	log.debug ("updating")
	if (pushToBreak) {
		state.pushToBreak = true
	}
	else {
		state.pushToBreak = false
	}
}

def configure() {
	log.debug ("configure() called")
	def commands = []
	commands << zwave.versionV1.versionGet().format()
	commands << zwave.batteryV1.batteryGet().format()
	delayBetween(commands,500)
}

def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd) {
	def event = createEvent(descriptionText: "${device.displayName} woke up", displayed: false)
	def result = []
    
	// Request battery info on wake up if levels have not been received within last 24 hours
	if (!state.lastBatteryReport || (new Date().time) - state.lastBatteryReport > 24*60*60*1000) {
		result += response(zwave.batteryV1.batteryGet().format())
		result += response("delay 1200")
	}
	result += response(zwave.wakeUpV1.wakeUpNoMoreInformation().format()) 
	return result
}

def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) {	
	//updateDataValue("applicationVersion", "${cmd.applicationVersion}")
	log.debug ("received Version Report")
	log.debug "applicationVersion:      ${cmd.applicationVersion}"
	log.debug "applicationSubVersion:   ${cmd.applicationSubVersion}"
	state.firmwareVersion=cmd.applicationVersion+'.'+cmd.applicationSubVersion
	log.debug "zWaveLibraryType:        ${cmd.zWaveLibraryType}"
	log.debug "zWaveProtocolVersion:    ${cmd.zWaveProtocolVersion}"
	log.debug "zWaveProtocolSubVersion: ${cmd.zWaveProtocolSubVersion}"
	setFirmwareVersion()
	createEvent([descriptionText: "Firmware V"+state.firmwareVersion, isStateChange: false])
}

// Unexpected command received
def zwaveEvent (physicalgraph.zwave.Command cmd) {
	log.debug("Unhandled Command: $cmd")
	return createEvent(descriptionText: cmd.toString(), isStateChange: false)
}

def switchOffVerification() {
	if (state.bellIsRinging) {
		log.debug("${device.displayName} switchOffVerification setting switch off")
		sendEvent(name: "status", value: "off", descriptionText: "Button released via verification check", isStateChange: true)
	}
	state.bellIsRinging = false
	sendEvent(name: "status", value: "off", displayed: false, isStateChange: true)
	sendEvent(name: "switch", value: "off", displayed: false, isStateChange: true)
	sendEvent(name: "contact", value: "closed", displayed: false, isStateChange: true)      
}

//Battery Level received
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
	def result = null
	state.lastBatteryReport = new Date().time
	def batteryLevel = cmd.batteryLevel
	log.info("Battery: $batteryLevel")
	result = createEvent(name: "battery", value: batteryLevel, unit: "%", descriptionText: "Battery%: $batteryLevel", isStateChange: true)   
	return result
}

//Notification received
def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd) {
	def result = []

	// if the bell is not already ringing, record as a button press. We can't always trust an event of 1 to be a 
	// button press if messages arrive out of order or are missed

	if (!state.bellIsRinging) { 
		if (!pushToBreak | cmd.event == 0) //Event 1 will never be a doorbell trigger for a push to break circuit
		{
			// bell is not ringing - signal a button press
			state.bellIsRinging = true 
			log.debug("${device.displayName} notification event = $cmd.event triggered switch on")
			runIn(10, switchOffVerification) //set to turn off switch in 10 seconds in case the button release event is missed   
			result += createEvent(name: "status", value: "doorbell", descriptionText: "Button pressed", isStateChange: true)
			result += createEvent(name: "switch", value: "on", displayed: false, isStateChange: true)
			result += createEvent(name: "momentary", value: "pushed", displayed: false, isStateChange: true)
			result += createEvent(name: "button", value: "pushed", data: [buttonNumber: "1"], displayed: false, isStateChange: true)
			result += createEvent(name: "contact", value: "open", displayed: false, isStateChange: true)             
        }
	} else {
		// bell is ringing - signal a button release
		state.bellIsRinging = false
		log.debug("${device.displayName} notification event = $cmd.event triggered switch off")
		result += createEvent(name: "status", value: "off", descriptionText: "Button released", isStateChange: true)
		result += createEvent(name: "switch", value: "off", displayed: false, isStateChange: true)
		result += createEvent(name: "contact", value: "closed", displayed: false, isStateChange: true)             
    }
	return result
}

def setFirmwareVersion() {
	def versionInfo = ''
	if (state.firmwareVersion) {
		versionInfo=versionInfo+"Firmware V"+state.firmwareVersion
	}
	else {
		versionInfo=versionInfo+"Firmware unknown"
	}
	sendEvent(name: "firmwareVersion",  value: versionInfo, isStateChange: true)
}

def parse(description) {
	def result = null
	log.debug (description)
	if (description.startsWith("Err")) {
		result = createEvent(descriptionText: description, isStateChange: true)
	} else if (description != "updated") {
		def cmd = zwave.parse(description, [0x71: 3, 0x80: 1])
		if (cmd) {
			result = zwaveEvent(cmd)
		} else {
			log.debug("Couldn't zwave.parse '$description'")
		}
	}
	return result
}