[RELEASE] Fibaro FGBS-001 Universal Binary Sensor (UBS)

Yep, messed up both my installs. Looking at the DTH, I can see the endpoint stuff that seems to be the issue. I have no idea how to fix it myself though. Hopefully @cjcharles will pop long and have a look.

Just seen this when I noticed quite a few of my own devices weren’t working!

Will try and have a look at this tonight, if anybody has started investigating or has ideas for a fix them please let me know to give me a headstart later (I haven’t looked at zwave associations in 2 years)!

2 Likes

It may be something to do with the ubs not sending unsolicited communications to the correct endpoint.

This may be relevant from:
Kianoosh_Karami
SmartThings Staff
10h

"The current status of the Z-Wave issue is that affected multi channel devices are sending unsolicited messages to endpoint 1 instead of endpoint 0. In the 0.30.X release, we upgraded our Z-Wave middleware (minor version bump) which included various fixes, needless to say in the latest SDK, there was a change to drop messages sent to hub with destination endpoint that was not 0 (Following the specification) and this change is now impacting these selected multi channel devices.

We are investigating the issue further, we’d like to be Z-Wave compliant as much as we can so we need to understand what prompted these devices to be sending a message to endpoint 1. The DTHs could potentially tell the device (Via association) to send unsolicited messages to different points other than 0.

I will keep you in the loop, if you have a Fibaro device that is affected, I have a potential fix that I would like you to validate for me (Self publishing a modified DTH). So if you are up for it, please PM me."

@cscheiene Do you think it’s possible to implement refresh capability (zwave)?
I have also a Fibaro double switch with the same issue and if i press refresh the status arrives correctly.

This can be useful until Smartthings fixes the firmware but also if you need to refresh the status.
Here the code from the other device type

def refresh() {
	def cmds = []
    (1..2).each { endpoint ->
        cmds << encap(zwave.switchBinaryV1.switchBinaryGet(), endpoint)
		cmds << encap(zwave.meterV2.meterGet(scale: 0), endpoint)
        cmds << encap(zwave.meterV2.meterGet(scale: 2), endpoint)
	}
    log.debug "Refresh $cmds"
	commands(cmds, 1000)
}

Thanks
M

Hello all,
I have tried to “increase” @cjcharles device type exploiting also basic report.
This updates the status of ep1 when basic report is received. This works just for endpoint1 because the report refers just to EP1.

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd)
{
    def result
    def currentstate
    def motionstate
    
	if (cmd.value == 0) 
    {
       	currentstate = "closed"
        motionstate = "active"
	}
	else
    {
      	currentstate = "open"
        motionstate = "inactive"
	}
    log.debug "Basic report: ep1 is ${currentstate}"
    //First update tile on this device
    sendEvent(name: "contact1", value: currentstate, descriptionText: "$device.displayName - ep1 is ${currentstate}")
	//If not null then we have found either ep1 or ep2, hence try to send to the child device aswell
    try {
        def childDevice = getChildDevices()?.find { it.deviceNetworkId == "${device.deviceNetworkId}-ep1"}
        if (childDevice)
        	if(childDevice.currentValue("contact") != currentstate || childDevice.currentValue("motion") != motionstate)
            {
            	childDevice.sendEvent(name: "motion", value: motionstate)
            	childDevice.sendEvent(name: "contact", value: currentstate)
                log.debug "Updating state ${childDevice} to ${currentstate}/${motionstate}"
            }
    } catch (e) {
        log.error "Couldn't find child device, probably doesn't exist...? Error: ${e}"
    }    
	return result   
} 

I have 2 questions:
1 - @cjcharles do you think you can integrate this part in your device type?
2 - How can we add also the report for the second endpoint (EP2)?

Thanks a lot
Marco

Hello all, i found a workaround to make Fibaro Universali Binary Sensor work again (just the contacts, not temperature)

  1. Insert this code at the end of Device Handler made by cjcharles
  2. Set Parameter 14 to value 1
  3. Press Send Config in the IDE of Fibaro UBS
  4. Enjoy

NOTE: when Smartthings will fix the multichannel bug just set Parameter 14 to 0

//NEED TO SET PARAMETER 14 (SCENES) TO VALUE 1 IN ORDER TO WORK PROPERLY
def zwaveEvent(physicalgraph.zwave.commands.sceneactivationv1.SceneActivationSet cmd) {
	def value = cmd.sceneId
    def result	
    def ep
    def currentstate
    def motionstate
    
    if (value == 10)
    {
    	ep="1"
       	currentstate = "open"
        motionstate = "inactive"       
    }
    else if (value == 11)
    {
    	ep="1"
       	currentstate = "closed"
        motionstate = "active"     
    }
    else if (value == 20)
    {
    	ep="2"
       	currentstate = "open"
        motionstate = "inactive"       
    }
    else if (value == 21)
    {
    	ep="2"
       	currentstate = "closed"
        motionstate = "active"     
    }	
    
    log.debug "Scene report: ${ep} is ${currentstate}"

    //First update tile on this device
    sendEvent(name: "contact${ep}", value: currentstate, descriptionText: "$device.displayName - ep${ep} is ${currentstate}")
	//If not null then we have found either ep1 or ep2, hence try to send to the child device aswell
    try {
        def childDevice = getChildDevices()?.find { it.deviceNetworkId == "${device.deviceNetworkId}-ep${ep}"}
        if (childDevice)
        	if(childDevice.currentValue("contact") != currentstate || childDevice.currentValue("motion") != motionstate)
            {
            	childDevice.sendEvent(name: "motion", value: motionstate)
            	childDevice.sendEvent(name: "contact", value: currentstate)
                log.debug "Updating state ${childDevice} to ${currentstate}/${motionstate}"
            }
    } catch (e) {
        log.error "Couldn't find child device, probably doesn't exist...? Error: ${e}"
    }    
	return result 	
}
2 Likes

Not sure if I understand, so I’m currently using cjcharles handler, I copy/pasted your code onto the end of it and republished. Then altered 14 to 1. Or have I totally misunderstood and I should be using a completely different DTH and adding this to the end?

Thanks for your efforts!

?

You are right!

Yeah. In that case doesn’t work here I’m afraid.

Did u press “send Config” in the IDE of the UBS?

Looks ike this is to fix the contact sensors? How about temperature probes?

that is impossible until Smarthings fixes the hub. This is a Workaround to manage scenes that are not broken by Smartthings 30.3.
Scenes triggered by temperature are not available in Fibaro UBS manual. sorry.

Cheers. Thought so.

Ah… That makes sense. Temp sensors aren’t working, but the contact sensors are. =)

better than nothing :slight_smile: i have updated my old post so that others can unserstand from the beginning :stuck_out_tongue:

At least my alarm keypad works again, so that’s handy. Thanks again.

Now, if the staff could just get this minor firmware update out (which was supposed to be Friday), then perhaps we could get things back to normal! = p

thanks! i had my alarm system triggering my locks, and used the module for this…
i was pulling every hair because of the bug!

you saved my week!

1 Like

Hi, the tech guys at smarttthings managed to get my UBS working (including temperature sensors) last night. Thought it may be worth posting here for others. Many thanks to cjcharles for the original.

So… original

/**
 *  Device Type Definition File
 *
 *  Device Type:		Fibaro UBS - Dual Contact and Temperature Sensor
 *  File Name:			Fibaro UBS - Dual Contact and Temperature Sensor.groovy
 *	Initial Release:	2017-11-07
 *	Author:				Chris Charles
 *
 *  Copyright 2017 Chris Charles, based on original code by carlos.ir33, modified
 *  by Stuart Buchanan and Paul Crookes. Testing thanks to borristhecat.
 *
 ***************************************************************************************
 */
 
metadata {
	definition (name: "Fibaro UBS", namespace: "cjcharles0", author: "Chris Charles") {
    
    capability "Contact Sensor"
 	capability "Motion Sensor"
    capability "Sensor"
	capability "Temperature Measurement"
    capability "Configuration"
    
    command "removeChildDevices"
    command "createChildDevices"
    command "createChildTempDevices"
    command "updateCurrentParams"
    command "listCurrentParams"
    command "open1"
    command "open2"
    command "close1"
    command "close2"
    
    attribute "contact1","enum",["open1","close1"]
    attribute "contact2","enum",["open2","close2"]
	
	fingerprint type: "2001", cc: "30 60 85 8E 72 70 86 7A", ccOut: "2B"
}

simulator {
}

tiles(scale: 2) {
	standardTile("contact1", "device.contact1", width: 3, height: 2) {
		state "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#e86d13", action: "close1"
		state "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#00a0dc", action: "open1"
	}
	standardTile("contact2", "device.contact2", width: 3, height: 2) {
		state "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#e86d13", action: "close2"
		state "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#00a0dc", action: "open2"
	}
	
	standardTile("temp1text", "temp1text", inactiveLabel: false, decoration: "flat", width: 2, height: 1) {
		state "default", label:'Temp 1:', action:"", icon:""
	}
	standardTile("temp2text", "temp2text", inactiveLabel: false, decoration: "flat", width: 2, height: 1) {
		state "default", label:'Temp 2:', action:"", icon:""
	}
	standardTile("temp3text", "temp3text", inactiveLabel: false, decoration: "flat", width: 2, height: 1) {
		state "default", label:'Temp 3:', action:"", icon:""
	}
	standardTile("temp4text", "temp4text", inactiveLabel: false, decoration: "flat", width: 2, height: 1) {
		state "default", label:'Temp 4:', action:"", icon:""
	}
	valueTile("temperature1", "temperature1", width:1, height:1, decoration: "flat") {
		state "default", label:'${currentValue}°', unit:"C", backgroundColor:"#fab907"//, icon:"st.Weather.weather2"
    }
	valueTile("temperature2", "temperature2", width:1, height:1, decoration: "flat") {
		state "default", label:'${currentValue}°', unit:"C", backgroundColor:"#fab907"//, icon:"st.Weather.weather2"
    }
	valueTile("temperature3", "temperature3", width:1, height:1, decoration: "flat") {
		state "default", label:'${currentValue}°', unit:"C", backgroundColor:"#fab907"//, icon:"st.Weather.weather2"
    }
    valueTile("temperature4", "temperature4", width:1, height:1, decoration: "flat") {
		state "default", label:'${currentValue}°', unit:"C", backgroundColor:"#fab907"//, icon:"st.Weather.weather2"
    }

	standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat", width: 3, height: 1) {
		state "default", label:'Send Config', action:"updateCurrentParams"//, icon:"st.secondary.configure"
	}
	standardTile("report", "device.report", inactiveLabel: false, decoration: "flat", width: 3, height: 1) {
		state "default", label:'List Config', action:"listCurrentParams"
	}
    
    standardTile("createchildren", "createchildren", inactiveLabel: false, decoration: "flat", width: 2, height: 1) {
		state "default", label:'Create Contact Children', action:"createChildDevices"
	}
    standardTile("createtempchildren", "createtempchildren", inactiveLabel: false, decoration: "flat", width: 2, height: 1) {
		state "default", label:'Create Temperature Children', action:"createChildTempDevices"
	}
    standardTile("removechildren", "removechildren", inactiveLabel: false, decoration: "flat", width: 2, height: 1) {
		state "default", label:'Remove Child Devices', action:"removeChildDevices"
	}
}

main(["contact1"]) //, "temperature1"
details(["contact1","contact2",
		"temp1text", "temperature1", "temp2text", "temperature2",
        "temp3text", "temperature3", "temp4text", "temperature4",
        "configure", "report", "createchildren", "createtempchildren", "removechildren"])

preferences {
        input name: "Info", type: "paragraph", title:"Device Handler by @cjcharles", description: "Parameter Settings:", displayDuringSetup: false

        input name: "param1", type: "number", range: "0..65535", required: true, //defaultValue: "0",
            title: "Parameter No. 1 - Input 1 Alarm Cancellation Delay. \n" +
                   "Additional delay after an alarm from input 1 has ceased.\n" +
                   "Time in seconds to delay the ceasing event.\n" +
                   "Default value: 0."
       
        input name: "param2", type: "number", range: "0..65535", required: true, //defaultValue: "0",
            title: "Parameter No. 2 - Input 2 Alarm Cancellation Delay. \n" +
                   "Additional delay after an alarm from input 2 has ceased.\n" +
                   "Time in seconds to delay the ceasing event.\n" +
                   "Default value: 0."
       
        input name: "param3", type: "number", range: "0..3", required: true, //defaultValue: "1",
            title: "Parameter No. 3 - Type of Input No 1." +
                   "Available settings:\n" +
                   "0 – INPUT_NO (Normal Open)\n" +
				   "1 – INPUT_NC (Normal Close)\n" +
				   "2 – INPUT_MONOSTABLE\n" +
				   "3 – INPUT_BISTABLE\n" +
                   "Default value: 1."

		input name: "param4", type: "number", range: "0..3", required: true, //defaultValue: "1",
            title: "Parameter No. 4 - Type of Input No 2." +
                   "Available settings:\n" +
                   "0 – INPUT_NO (Normal Open)\n" +
				   "1 – INPUT_NC (Normal Close)\n" +
				   "2 – INPUT_MONOSTABLE\n" +
				   "3 – INPUT_BISTABLE\n" +
                   "Default value: 1."

		input name: "param5", type: "number", range: "0..255", required: true, //defaultValue: "255",
            title: "Parameter No. 5 - Type of transmitted control or alarm frame for association group 1." +
                   "Available settings:\n" +
				   "0 – Frame ALARM GENERIC\n" +
				   "1 – Frame ALARM SMOKE\n" +
				   "2 – Frame ALARM CO\n" +
				   "3 – Frame ALARM CO2\n" +
				   "4 – Frame ALARM HEAT\n" +
				   "5 – Frame ALARM WATER\n" +
				   "255 – Control frame BASIC_SET\n" +
                   "Default value: 255."

		input name: "param6", type: "number", range: "0..255", required: true, //defaultValue: "255",
            title: "Parameter No. 6 - Type of transmitted control or alarm frame for association group 2." +
                   "Available settings:\n" +
				   "0 – Frame ALARM GENERIC\n" +
				   "1 – Frame ALARM SMOKE\n" +
				   "2 – Frame ALARM CO\n" +
				   "3 – Frame ALARM CO2\n" +
				   "4 – Frame ALARM HEAT\n" +
				   "5 – Frame ALARM WATER\n" +
				   "255 – Control frame BASIC_SET\n" +
                   "Default value: 255."

		input name: "param7", type: "number", range: "0..255", required: true, //defaultValue: "255",
            title: "Parameter No. 7 - Value of the parameter specifying the forced level of dimming / opening sun blinds when " +
            	   "sent a “switch on” / ”open” command from association group no. 1.\n" +
                   "Available settings:\n" +
                   "0-99 - Dimming or Opening Percentage\n" +
                   "255 - Last set percentage\n" +
                   "Default value: 255."

		input name: "param8", type: "number", range: "0..255", required: true, //defaultValue: "255",
            title: "Parameter No. 8 - Value of the parameter specifying the forced level of dimming / opening sun blinds when " +
            	   "sent a “switch on” / ”open” command from association group no. 2.\n" +
                   "Available settings:\n" +
                   "0-99 - Dimming or Opening Percentage\n" +
                   "255 - Last set percentage\n" +
                   "Default value: 255."

		input name: "param9", type: "number", range: "0..3", required: true, //defaultValue: "0",
            title: "Parameter No. 9 - Deactivating transmission of the frame cancelling the alarm or the " +
				   "control frame deactivating the device (Basic). Disable the alarm cancellation function.\n" +
                   "Available settings:\n" +
                   "0 – Cancellation sent for association group 1 and 2\n" +
				   "1 – Cancellation sent for association group 1 only\n" +
				   "2 – Cancellation sent for association group 2 only\n" +
				   "3 - Not sent for association group 1 or 2\n" +
                   "Default value: 0."

		input name: "param10", type: "number", range: "1..255", required: true, //defaultValue: "20",
            title: "Parameter No. 10 - Interval between successive readings of temperature from all " +
				   "sensors connected to the device. (A reading does not result in sending to ST)\n" +
                   "Available settings:\n" +
                   "1-255 - Seconds between readings\n" +
                   "Default value: 20."

		input name: "param11", type: "number", range: "0..255", required: true, //defaultValue: "200",
            title: "Parameter No. 11 - Interval between forcing to send report of the temperature. " +
				   "The forced report is sent immediately after the next temperature reading, " +
				   "irrespective of parameter 12. Advised to be 200 unless rapid temperature changes are expected.\n" +
                   "Available settings:\n" +
                   "0 - Deactivate temperature sending\n" +
                   "1-255 - Seconds between sends\n" +
                   "Default value: 200."

		input name: "param12", type: "number", range: "0..255", required: true, //defaultValue: "8",
            title: "Parameter No. 12 - Insensitiveness to temperature changes. This is the maximum " +
				   "difference between the last reported temperature and the current temperature. " +
				   "If they differ by more than this then a report is sent.\n" +
                   "Available settings:\n" +
                   "0-255 - x/16 = temp diff in C\n" +
                   "x/80*9 = temp diff in F\n" +
                   "Default value: 8 (0.5oC)."

		input name: "param13", type: "number", range: "0..3", required: true, //defaultValue: "0",
            title: "Parameter No. 13 - Transmitting the alarm or control frame in “broadcast” mode (i.e. to " +
				   "all devices within range), this information is not repeated by the mesh network." +
                   "Available settings:\n" +
                   "0 - IN1 and IN2 broadcast inactive,\n" +
                   "1 - IN1 broadcast mode active only,\n" +
                   "2 - IN2 broadcast mode active only,\n" +
                   "3 - INI and IN2 broadcast mode active.\n" +
                   "Default value: 0."

		input name: "param14", type: "number", range: "0..1", required: true, //defaultValue: "0",
            title: "Parameter No. 14 - Scene activation functionality." +
                   "Available settings:\n" +
                   "0 - Deactivated functionality,\n" +
                   "1 - Activated functionality.\n" +
                   "Default value: 0."
	}
}

def installed() {
	log.debug "installed()"
}
def updated() {
	log.debug "updated()"
	log.debug "Dont forget to press the button to send config to the device"
    //configure()
    //createChildDevices()
}
def uninstalled() {
    log.debug "uninstalled()"
    removeChildDevices()
}

def configure() {
	log.debug "configure()"
    updateCurrentParams()
}

def createChildDevices(){
	log.debug "Adding Child Devices if not already added"
    for (i in 1..2) {
    	try {
        	log.debug "Trying to create child switch if it doesn't already exist ${i}"
            def currentchild = getChildDevices()?.find { it.deviceNetworkId == "${device.deviceNetworkId}-ep${i}"}
            if (currentchild == null) {
            	log.debug "Creating child for ep${i}"
				addChildDevice("smartthings", "Open/Closed Sensor", "${device.deviceNetworkId}-ep${i}", device.hub.id,
                	[completedSetup: true, name: "${device.displayName} (Contact${i})", isComponent: false]) //, label: "${device.displayName} (Contact${i})"
                /*addChildDevice(deviceHandlerName, "${device.deviceNetworkId}-${deviceName}${deviceNumber}", null,
         			[completedSetup: true, label: "${device.displayName} (${deviceName}${deviceNumber})", 
                	isComponent: false, componentName: "${deviceName}${deviceNumber}", componentLabel: "${deviceName} ${deviceNumber}"])*/
            }
        } catch (e) {
            log.debug "Error adding child ${i}: ${e}"
        }
    }
}
def createChildTempDevices() {
    log.debug "Creating Temperature children"
    for (i in 1..4) {
    	try {
        	//If we have a temperature reading from this sensor (1 to 4) then try to create a child for it
        	if (device.currentValue("temperature${i}") != null) {
            	log.debug "Have received temperature readings for termperature${i} so creating a child for it if not already there"
                def currentchild = getChildDevices()?.find { it.deviceNetworkId == "${device.deviceNetworkId}-temperature${i}"}
                if (currentchild == null) {
                    addChildDevice("smartthings", "Temperature Sensor", "${device.deviceNetworkId}-temperature${i}", device.hub.id,
                        [completedSetup: true, name: "${device.displayName} (Temp${i})", isComponent: false]) //, label: "${device.displayName} (Temp${i})"
                }
            }
            else {
            	log.debug "No temperature received for temperature${i} so no child will be created" 
            }
        } catch (e) {
            log.debug "Error adding Temperature # ${i} child: ${e}"
        }
    }
}
private removeChildDevices() {
	log.debug "Removing Child Devices"
    try {
        getChildDevices()?.each {
        	try {
            	deleteChildDevice(it.deviceNetworkId)
            } catch (e) {
                log.debug "Error deleting ${it.deviceNetworkId}, probably locked into a SmartApp: ${e}"
            }
        }
    } catch (err) {
        log.debug "Either no children exist or error finding child devices for some reason: ${err}"
    }
}

def parse(String description) {
	def result = null
	def cmd = zwave.parse(description, [ 0x60: 3])
	if (cmd) {
		result = zwaveEvent(cmd)
	}
	log.debug "parsed '$description' to result: ${result}"
	return result
}

def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv1.ManufacturerSpecificReport cmd) {
	log.debug("ManufacturerSpecificReport ${cmd.inspect()}")
}

def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {
	log.debug("ConfigurationReport ${cmd.inspect()}")
}

def createEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd, Map item1) { 
	log.debug "manufacturerId:   ${cmd.manufacturerId}"
    log.debug "manufacturerName: ${cmd.manufacturerName}"
    log.debug "productId:        ${cmd.productId}"
    log.debug "productTypeId:    ${cmd.productTypeId}"

}

def createEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd, Map item1) {	
    updateDataValue("applicationVersion", "${cmd.applicationVersion}")
    log.debug "applicationVersion:      ${cmd.applicationVersion}"
    log.debug "applicationSubVersion:   ${cmd.applicationSubVersion}"
    log.debug "zWaveLibraryType:        ${cmd.zWaveLibraryType}"
    log.debug "zWaveProtocolVersion:    ${cmd.zWaveProtocolVersion}"
    log.debug "zWaveProtocolSubVersion: ${cmd.zWaveProtocolSubVersion}"
}

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
	log.debug "BasicSet V1 ${cmd.inspect()}"
    def currentstate
    def motionstate
	if (cmd.value) {
		currentstate = "open"
        motionstate = "inactive"
	} else {
    	currentstate = "closed"
        motionstate = "active"
	}
    createEvent(name: "contact1", value: currentstate, descriptionText: "${device.displayName} is ${currentstate}")
    try {
        def childDevice = getChildDevices()?.find { it.deviceNetworkId == "${device.deviceNetworkId}-ep1"}
        if (childDevice)
        	childDevice.sendEvent(name: "motion", value: motionstate)
            childDevice.sendEvent(name: "contact", value: currentstate)
            log.debug "Fibaro is ${motionstate} and ${currentstate}"
    } catch (e) {
        log.error "Couldn't find child device, probably doesn't exist...? Error: ${e}"
    }
}

def zwaveEvent(physicalgraph.zwave.commands.multichannelv3.MultiChannelCmdEncap cmd) {
	log.debug "ZWaveEvent V3 ${cmd.inspect()}"
	def result
	if (cmd.commandClass == 32) {
        def currentstate
        def motionstate
		if (cmd.parameter == [0]) {
        	currentstate = "closed"
            motionstate = "active"
		}
		if (cmd.parameter == [255]) {
        	currentstate = "open"
            motionstate = "inactive"
		}
        log.debug "ep${cmd.sourceEndPoint} is ${currentstate}"
        //First update tile on this device
        sendEvent(name: "contact${cmd.sourceEndPoint}", value: currentstate, descriptionText: "$device.displayName - ep${cmd.sourceEndPoint} is ${currentstate}")
		//If not null then we have found either ep1 or ep2, hence try to send to the child device aswell
        try {
            def childDevice = getChildDevices()?.find { it.deviceNetworkId == "${device.deviceNetworkId}-ep${cmd.sourceEndPoint}"}
            if (childDevice)
                childDevice.sendEvent(name: "motion", value: motionstate)
                childDevice.sendEvent(name: "contact", value: currentstate)
        } catch (e) {
            log.error "Couldn't find child device, probably doesn't exist...? Error: ${e}"
        }
    }
	else if (cmd.commandClass == 49) {
		if ((cmd.sourceEndPoint >= 3) && (cmd.sourceEndPoint <= 6)) {
            
			def tempsensorid = cmd.sourceEndPoint - 2
			def tempendpoint = "temperature" + tempsensorid.toString()
			
            def tempval = ((cmd.parameter[4] * 256) + cmd.parameter[5])
            if (tempval > 32767) {
            	//Here we deal with negative values
            	tempval = tempval - 65536
            }
            //Finally round the temperature
            def tempprocessed = (tempval / 100).toDouble().round(1)
            
			//def cmdScale = cmd.scale == 1 ? "F" : "C"
			//def tempval = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmdScale, cmd.precision).toDouble().round(1)
            
            log.debug "${tempendpoint} has changed to ${tempprocessed}"
            
            sendEvent(name: tempendpoint, value: tempprocessed, displayed: true) //unit: getTemperatureScale()
            
			//If not null then we have found either contact1 or contact2, hence try to send to the child
            try {
                def childDevice = getChildDevices()?.find { it.deviceNetworkId == "${device.deviceNetworkId}-${tempendpoint}"}
                if (childDevice)
                	//We found a child device that matches so send it the new temperature
                    childDevice.sendEvent(name: "temperature", value: tempprocessed)
            } catch (e) {
            	//Not an error message here as people may not want child temperature devices
                log.debug "Couldn't find child ${tempendpoint} device, probably doesn't exist...? Error: ${e}"
            }
        }
	}
	else {
		//Send them here just in case we want to do more complicated processing (not doing it as need to have endpoint passed and that makes it a bit messy)
		def encapsulatedCommand = cmd.encapsulatedCommand([0x31: 2, 0x60: 3, 0x85: 2, 0x8E: 2, 0x72: 1, 0x70: 1, 0x86: 1, 0x7A: 1, 0xEF: 1, 0x2B: 1]) // can specify command class versions here like in zwave.parse
		log.debug ("Command from endpoint ${cmd.sourceEndPoint}: ${encapsulatedCommand}")
		if (encapsulatedCommand) {
			result = zwaveEvent(encapsulatedCommand)
		}
	}
    return result
}

def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv2.SensorMultilevelReport cmd)
{
	//This is no longer used as caught in an earlier event, but kept here in case the code is useful
	log.debug "Sensor MultiLevel Report - Sensor Type = ${cmd.sensorType}"
	switch (cmd.sensorType) {
		case 1:
			// temperature
			def cmdScale = cmd.scale == 1 ? "F" : "C"
			def tempval = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmdScale, cmd.precision).toDouble().round(1)
            sendEvent(name: "temperature1", value: tempval, displayed: false) //unit: getTemperatureScale()
			break;
	}
    log.debug map
	createEvent(map)
}

def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv1.SensorMultilevelReport cmd) {
    log.debug "SensorMultilevelReport $cmd"
}

def zwaveEvent(physicalgraph.zwave.Command cmd) {
	// This will capture any commands not handled by other instances of zwaveEvent
	// and is recommended for development so you can see every command the device sends
	log.debug "Catchall reached for cmd: ${cmd.toString()}}"
	return createEvent(descriptionText: "${device.displayName}: ${cmd}")
}

def updateCurrentParams() {
	log.debug "Sending configuration parameters to device"
    def cmds = []
	cmds << zwave.multiChannelAssociationV2.multiChannelAssociationSet(groupingIdentifier:2, nodeId:[zwaveHubNodeId]).format()
	cmds << zwave.associationV2.associationSet(groupingIdentifier:3, nodeId:[zwaveHubNodeId]).format()
	cmds << zwave.associationV1.associationRemove(groupingIdentifier:1, nodeId:zwaveHubNodeId).format()
	cmds << zwave.configurationV1.configurationSet(parameterNumber: 1, configurationValue:[param1.value]).format()
	cmds << zwave.configurationV1.configurationSet(parameterNumber: 2, configurationValue:[param2.value]).format()
	cmds << zwave.configurationV1.configurationSet(parameterNumber: 3, configurationValue:[param3.value]).format()
	cmds << zwave.configurationV1.configurationSet(parameterNumber: 4, configurationValue:[param4.value]).format()
	cmds << zwave.configurationV1.configurationSet(parameterNumber: 5, configurationValue:[param5.value]).format()
    cmds << zwave.configurationV1.configurationSet(parameterNumber: 6, configurationValue:[param6.value]).format()
	cmds << zwave.configurationV1.configurationSet(parameterNumber: 7, configurationValue:[param7.value]).format()
	cmds << zwave.configurationV1.configurationSet(parameterNumber: 8, configurationValue:[param8.value]).format()
	cmds << zwave.configurationV1.configurationSet(parameterNumber: 9, configurationValue:[param9.value]).format()
    cmds << zwave.configurationV1.configurationSet(parameterNumber: 10, configurationValue:[param10.value]).format()
    cmds << zwave.configurationV1.configurationSet(parameterNumber: 11, configurationValue:[param11.value]).format()
    cmds << zwave.configurationV1.configurationSet(parameterNumber: 12, configurationValue:[param12.value]).format()
	cmds << zwave.configurationV1.configurationSet(parameterNumber: 13, configurationValue:[param13.value]).format()
    cmds << zwave.configurationV1.configurationSet(parameterNumber: 14, configurationValue:[param14.value]).format()
	delayBetween(cmds, 500)
}
def listCurrentParams() {
	log.debug "Listing of current parameter settings of ${device.displayName}"
    def cmds = []
	cmds << zwave.multiChannelAssociationV2.multiChannelAssociationGet(groupingIdentifier:2).format()
	cmds << zwave.associationV2.associationGet(groupingIdentifier: 3).format()
	cmds << zwave.associationV1.associationGet(groupingIdentifier: 1).format()
	cmds << zwave.configurationV1.configurationGet(parameterNumber: 1).format()
	cmds << zwave.configurationV1.configurationGet(parameterNumber: 2).format()
   	cmds << zwave.configurationV1.configurationGet(parameterNumber: 3).format()
	cmds << zwave.configurationV1.configurationGet(parameterNumber: 4).format()
	cmds << zwave.configurationV1.configurationGet(parameterNumber: 5).format()
	cmds << zwave.configurationV1.configurationGet(parameterNumber: 6).format()
    cmds << zwave.configurationV1.configurationGet(parameterNumber: 7).format()
	cmds << zwave.configurationV1.configurationGet(parameterNumber: 8).format()
   	cmds << zwave.configurationV1.configurationGet(parameterNumber: 9).format()
	cmds << zwave.configurationV1.configurationGet(parameterNumber: 10).format()
	cmds << zwave.configurationV1.configurationGet(parameterNumber: 11).format()
   	cmds << zwave.configurationV1.configurationGet(parameterNumber: 12).format()
	cmds << zwave.configurationV1.configurationGet(parameterNumber: 13).format()
	cmds << zwave.configurationV1.configurationGet(parameterNumber: 14).format()
	delayBetween(cmds, 500)
}

def open1() {
    sendEvent(name: "contact1", value: "open", descriptionText: "$device.displayName (1) is opened manually")
    try {
        def childDevice = getChildDevices()?.find { it.deviceNetworkId == "${device.deviceNetworkId}-ep1"}
        log.debug "Changing child ${childDevice} to open/inactive"
        if (childDevice)
        	childDevice.sendEvent(name: "motion", value: "inactive")
            childDevice.sendEvent(name: "contact", value: "open")
    } catch (e) {
        log.error "Couldn't find child device, probably doesn't exist...? Error: ${e}"
    }
}

def close1() {
    sendEvent(name: "contact1", value: "closed", descriptionText: "$device.displayName (1) is closed manually")
    try {
        def childDevice = getChildDevices()?.find { it.deviceNetworkId == "${device.deviceNetworkId}-ep1"}
        log.debug "Changing child ${childDevice} to closed/active"
        if (childDevice)
        	childDevice.sendEvent(name: "motion", value: "active")
            childDevice.sendEvent(name: "contact", value: "closed")
    } catch (e) {
        log.error "Couldn't find child device, probably doesn't exist...? Error: ${e}"
    }
}

def open2() {
    sendEvent(name: "contact2", value: "open", descriptionText: "$device.displayName (2) is opened manually")
    try {
        def childDevice = getChildDevices()?.find { it.deviceNetworkId == "${device.deviceNetworkId}-ep2"}
        log.debug "Changing child ${childDevice} to open/inactive"
        if (childDevice)
        	childDevice.sendEvent(name: "motion", value: "inactive")
            childDevice.sendEvent(name: "contact", value: "open")
    } catch (e) {
        log.error "Couldn't find child device, probably doesn't exist...? Error: ${e}"
    }
}

def close2() {
    sendEvent(name: "contact2", value: "closed", descriptionText: "$device.displayName (2) is closed manually")
    try {
        def childDevice = getChildDevices()?.find { it.deviceNetworkId == "${device.deviceNetworkId}-ep2"}
        log.debug "Changing child ${childDevice} to closed/active"
        if (childDevice)
        	childDevice.sendEvent(name: "motion", value: "active")
			childDevice.sendEvent(name: "contact", value: "closed")
    } catch (e) {
        log.error "Couldn't find child device, probably doesn't exist...? Error: ${e}"
    }
}

(…to be continued…)

…And the version I’m using now:

/**
 *  Device Type Definition File
 *
 *  Device Type:		Fibaro UBS - Dual Contact and Temperature Sensor
 *  File Name:			Fibaro UBS - Dual Contact and Temperature Sensor.groovy
 *	Initial Release:	2017-11-07
 *	Author:				Chris Charles
 *
 *  Copyright 2017 Chris Charles, based on original code by carlos.ir33, modified
 *  by Stuart Buchanan and Paul Crookes. Testing thanks to borristhecat.
 *
 ***************************************************************************************
 */
 
metadata {
	definition (name: "Fibaro UBS", namespace: "cjcharles0", author: "Chris Charles") {
    
    capability "Contact Sensor"
 	capability "Motion Sensor"
    capability "Sensor"
	capability "Temperature Measurement"
    capability "Configuration"
    
    command "removeChildDevices"
    command "createChildDevices"
    command "createChildTempDevices"
    command "updateCurrentParams"
    command "listCurrentParams"
    command "open1"
    command "open2"
    command "close1"
    command "close2"
    
    attribute "contact1","enum",["open1","close1"]
    attribute "contact2","enum",["open2","close2"]
	
	fingerprint type: "2001", cc: "30 60 85 8E 72 70 86 7A", ccOut: "2B"
}

simulator {
}

tiles(scale: 2) {
	standardTile("contact1", "device.contact1", width: 3, height: 2) {
		state "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#e86d13", action: "close1"
		state "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#00a0dc", action: "open1"
	}
	standardTile("contact2", "device.contact2", width: 3, height: 2) {
		state "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#e86d13", action: "close2"
		state "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#00a0dc", action: "open2"
	}
	
	standardTile("temp1text", "temp1text", inactiveLabel: false, decoration: "flat", width: 2, height: 1) {
		state "default", label:'Temp 1:', action:"", icon:""
	}
	standardTile("temp2text", "temp2text", inactiveLabel: false, decoration: "flat", width: 2, height: 1) {
		state "default", label:'Temp 2:', action:"", icon:""
	}
	standardTile("temp3text", "temp3text", inactiveLabel: false, decoration: "flat", width: 2, height: 1) {
		state "default", label:'Temp 3:', action:"", icon:""
	}
	standardTile("temp4text", "temp4text", inactiveLabel: false, decoration: "flat", width: 2, height: 1) {
		state "default", label:'Temp 4:', action:"", icon:""
	}
	valueTile("temperature1", "temperature1", width:1, height:1, decoration: "flat") {
		state "default", label:'${currentValue}°', unit:"C", backgroundColor:"#fab907"//, icon:"st.Weather.weather2"
    }
	valueTile("temperature2", "temperature2", width:1, height:1, decoration: "flat") {
		state "default", label:'${currentValue}°', unit:"C", backgroundColor:"#fab907"//, icon:"st.Weather.weather2"
    }
	valueTile("temperature3", "temperature3", width:1, height:1, decoration: "flat") {
		state "default", label:'${currentValue}°', unit:"C", backgroundColor:"#fab907"//, icon:"st.Weather.weather2"
    }
    valueTile("temperature4", "temperature4", width:1, height:1, decoration: "flat") {
		state "default", label:'${currentValue}°', unit:"C", backgroundColor:"#fab907"//, icon:"st.Weather.weather2"
    }

	standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat", width: 3, height: 1) {
		state "default", label:'Send Config', action:"updateCurrentParams"//, icon:"st.secondary.configure"
	}
	standardTile("report", "device.report", inactiveLabel: false, decoration: "flat", width: 3, height: 1) {
		state "default", label:'List Config', action:"listCurrentParams"
	}
    
    standardTile("createchildren", "createchildren", inactiveLabel: false, decoration: "flat", width: 2, height: 1) {
		state "default", label:'Create Contact Children', action:"createChildDevices"
	}
    standardTile("createtempchildren", "createtempchildren", inactiveLabel: false, decoration: "flat", width: 2, height: 1) {
		state "default", label:'Create Temperature Children', action:"createChildTempDevices"
	}
    standardTile("removechildren", "removechildren", inactiveLabel: false, decoration: "flat", width: 2, height: 1) {
		state "default", label:'Remove Child Devices', action:"removeChildDevices"
	}
}

main(["contact1"]) //, "temperature1"
details(["contact1","contact2",
		"temp1text", "temperature1", "temp2text", "temperature2",
        "temp3text", "temperature3", "temp4text", "temperature4",
        "configure", "report", "createchildren", "createtempchildren", "removechildren"])

preferences {
        input name: "Info", type: "paragraph", title:"Device Handler by @cjcharles", description: "Parameter Settings:", displayDuringSetup: false

        input name: "param1", type: "number", range: "0..65535", required: true, //defaultValue: "0",
            title: "Parameter No. 1 - Input 1 Alarm Cancellation Delay. \n" +
                   "Additional delay after an alarm from input 1 has ceased.\n" +
                   "Time in seconds to delay the ceasing event.\n" +
                   "Default value: 0."
       
        input name: "param2", type: "number", range: "0..65535", required: true, //defaultValue: "0",
            title: "Parameter No. 2 - Input 2 Alarm Cancellation Delay. \n" +
                   "Additional delay after an alarm from input 2 has ceased.\n" +
                   "Time in seconds to delay the ceasing event.\n" +
                   "Default value: 0."
       
        input name: "param3", type: "number", range: "0..3", required: true, //defaultValue: "1",
            title: "Parameter No. 3 - Type of Input No 1." +
                   "Available settings:\n" +
                   "0 – INPUT_NO (Normal Open)\n" +
				   "1 – INPUT_NC (Normal Close)\n" +
				   "2 – INPUT_MONOSTABLE\n" +
				   "3 – INPUT_BISTABLE\n" +
                   "Default value: 1."

		input name: "param4", type: "number", range: "0..3", required: true, //defaultValue: "1",
            title: "Parameter No. 4 - Type of Input No 2." +
                   "Available settings:\n" +
                   "0 – INPUT_NO (Normal Open)\n" +
				   "1 – INPUT_NC (Normal Close)\n" +
				   "2 – INPUT_MONOSTABLE\n" +
				   "3 – INPUT_BISTABLE\n" +
                   "Default value: 1."

		input name: "param5", type: "number", range: "0..255", required: true, //defaultValue: "255",
            title: "Parameter No. 5 - Type of transmitted control or alarm frame for association group 1." +
                   "Available settings:\n" +
				   "0 – Frame ALARM GENERIC\n" +
				   "1 – Frame ALARM SMOKE\n" +
				   "2 – Frame ALARM CO\n" +
				   "3 – Frame ALARM CO2\n" +
				   "4 – Frame ALARM HEAT\n" +
				   "5 – Frame ALARM WATER\n" +
				   "255 – Control frame BASIC_SET\n" +
                   "Default value: 255."

		input name: "param6", type: "number", range: "0..255", required: true, //defaultValue: "255",
            title: "Parameter No. 6 - Type of transmitted control or alarm frame for association group 2." +
                   "Available settings:\n" +
				   "0 – Frame ALARM GENERIC\n" +
				   "1 – Frame ALARM SMOKE\n" +
				   "2 – Frame ALARM CO\n" +
				   "3 – Frame ALARM CO2\n" +
				   "4 – Frame ALARM HEAT\n" +
				   "5 – Frame ALARM WATER\n" +
				   "255 – Control frame BASIC_SET\n" +
                   "Default value: 255."

		input name: "param7", type: "number", range: "0..255", required: true, //defaultValue: "255",
            title: "Parameter No. 7 - Value of the parameter specifying the forced level of dimming / opening sun blinds when " +
            	   "sent a “switch on” / ”open” command from association group no. 1.\n" +
                   "Available settings:\n" +
                   "0-99 - Dimming or Opening Percentage\n" +
                   "255 - Last set percentage\n" +
                   "Default value: 255."

		input name: "param8", type: "number", range: "0..255", required: true, //defaultValue: "255",
            title: "Parameter No. 8 - Value of the parameter specifying the forced level of dimming / opening sun blinds when " +
            	   "sent a “switch on” / ”open” command from association group no. 2.\n" +
                   "Available settings:\n" +
                   "0-99 - Dimming or Opening Percentage\n" +
                   "255 - Last set percentage\n" +
                   "Default value: 255."

		input name: "param9", type: "number", range: "0..3", required: true, //defaultValue: "0",
            title: "Parameter No. 9 - Deactivating transmission of the frame cancelling the alarm or the " +
				   "control frame deactivating the device (Basic). Disable the alarm cancellation function.\n" +
                   "Available settings:\n" +
                   "0 – Cancellation sent for association group 1 and 2\n" +
				   "1 – Cancellation sent for association group 1 only\n" +
				   "2 – Cancellation sent for association group 2 only\n" +
				   "3 - Not sent for association group 1 or 2\n" +
                   "Default value: 0."

		input name: "param10", type: "number", range: "1..255", required: true, //defaultValue: "20",
            title: "Parameter No. 10 - Interval between successive readings of temperature from all " +
				   "sensors connected to the device. (A reading does not result in sending to ST)\n" +
                   "Available settings:\n" +
                   "1-255 - Seconds between readings\n" +
                   "Default value: 20."

		input name: "param11", type: "number", range: "0..255", required: true, //defaultValue: "200",
            title: "Parameter No. 11 - Interval between forcing to send report of the temperature. " +
				   "The forced report is sent immediately after the next temperature reading, " +
				   "irrespective of parameter 12. Advised to be 200 unless rapid temperature changes are expected.\n" +
                   "Available settings:\n" +
                   "0 - Deactivate temperature sending\n" +
                   "1-255 - Seconds between sends\n" +
                   "Default value: 200."

		input name: "param12", type: "number", range: "0..255", required: true, //defaultValue: "8",
            title: "Parameter No. 12 - Insensitiveness to temperature changes. This is the maximum " +
				   "difference between the last reported temperature and the current temperature. " +
				   "If they differ by more than this then a report is sent.\n" +
                   "Available settings:\n" +
                   "0-255 - x/16 = temp diff in C\n" +
                   "x/80*9 = temp diff in F\n" +
                   "Default value: 8 (0.5oC)."

		input name: "param13", type: "number", range: "0..3", required: true, //defaultValue: "0",
            title: "Parameter No. 13 - Transmitting the alarm or control frame in “broadcast” mode (i.e. to " +
				   "all devices within range), this information is not repeated by the mesh network." +
                   "Available settings:\n" +
                   "0 - IN1 and IN2 broadcast inactive,\n" +
                   "1 - IN1 broadcast mode active only,\n" +
                   "2 - IN2 broadcast mode active only,\n" +
                   "3 - INI and IN2 broadcast mode active.\n" +
                   "Default value: 0."

		input name: "param14", type: "number", range: "0..1", required: true, //defaultValue: "0",
            title: "Parameter No. 14 - Scene activation functionality." +
                   "Available settings:\n" +
                   "0 - Deactivated functionality,\n" +
                   "1 - Activated functionality.\n" +
                   "Default value: 0."
	}
}

def installed() {
	log.debug "installed()"
    runIn(30, "tempReadRequest")
}
def updated() {
	log.debug "updated()"
	log.debug "Dont forget to press the button to send config to the device"
    runIn(30, "tempReadRequest")
    //configure()
    //createChildDevices()
}
def uninstalled() {
    log.debug "uninstalled()"
    removeChildDevices()
}

def configure() {
	log.debug "configure()"
    updateCurrentParams()
}

def createChildDevices(){
	log.debug "Adding Child Devices if not already added"
    for (i in 1..2) {
    	try {
        	log.debug "Trying to create child switch if it doesn't already exist ${i}"
            def currentchild = getChildDevices()?.find { it.deviceNetworkId == "${device.deviceNetworkId}-ep${i}"}
            if (currentchild == null) {
            	log.debug "Creating child for ep${i}"
				addChildDevice("smartthings", "Open/Closed Sensor", "${device.deviceNetworkId}-ep${i}", device.hub.id,
                	[completedSetup: true, name: "${device.displayName} (Contact${i})", isComponent: false]) //, label: "${device.displayName} (Contact${i})"
                /*addChildDevice(deviceHandlerName, "${device.deviceNetworkId}-${deviceName}${deviceNumber}", null,
         			[completedSetup: true, label: "${device.displayName} (${deviceName}${deviceNumber})", 
                	isComponent: false, componentName: "${deviceName}${deviceNumber}", componentLabel: "${deviceName} ${deviceNumber}"])*/
            }
        } catch (e) {
            log.debug "Error adding child ${i}: ${e}"
        }
    }
}
def createChildTempDevices() {
    log.debug "Creating Temperature children"
    for (i in 1..4) {
    	try {
        	//If we have a temperature reading from this sensor (1 to 4) then try to create a child for it
        	if (device.currentValue("temperature${i}") != null) {
            	log.debug "Have received temperature readings for termperature${i} so creating a child for it if not already there"
                def currentchild = getChildDevices()?.find { it.deviceNetworkId == "${device.deviceNetworkId}-temperature${i}"}
                if (currentchild == null) {
                    addChildDevice("smartthings", "Temperature Sensor", "${device.deviceNetworkId}-temperature${i}", device.hub.id,
                        [completedSetup: true, name: "${device.displayName} (Temp${i})", isComponent: false]) //, label: "${device.displayName} (Temp${i})"
                }
            }
            else {
            	log.debug "No temperature received for temperature${i} so no child will be created" 
            }
        } catch (e) {
            log.debug "Error adding Temperature # ${i} child: ${e}"
        }
    }
}
private removeChildDevices() {
	log.debug "Removing Child Devices"
    try {
        getChildDevices()?.each {
        	try {
            	deleteChildDevice(it.deviceNetworkId)
            } catch (e) {
                log.debug "Error deleting ${it.deviceNetworkId}, probably locked into a SmartApp: ${e}"
            }
        }
    } catch (err) {
        log.debug "Either no children exist or error finding child devices for some reason: ${err}"
    }
}

def parse(String description) {
	def result = null
	def cmd = zwave.parse(description, [ 0x60: 3])
	if (cmd) {
		result = zwaveEvent(cmd)
	}
	log.debug "parsed '$description' to result: ${result}"
	return result
}

def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv1.ManufacturerSpecificReport cmd) {
	log.debug("ManufacturerSpecificReport ${cmd.inspect()}")
}

def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {
	log.debug("ConfigurationReport ${cmd.inspect()}")
}

def createEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd, Map item1) { 
	log.debug "manufacturerId:   ${cmd.manufacturerId}"
    log.debug "manufacturerName: ${cmd.manufacturerName}"
    log.debug "productId:        ${cmd.productId}"
    log.debug "productTypeId:    ${cmd.productTypeId}"

}

def createEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd, Map item1) {	
    updateDataValue("applicationVersion", "${cmd.applicationVersion}")
    log.debug "applicationVersion:      ${cmd.applicationVersion}"
    log.debug "applicationSubVersion:   ${cmd.applicationSubVersion}"
    log.debug "zWaveLibraryType:        ${cmd.zWaveLibraryType}"
    log.debug "zWaveProtocolVersion:    ${cmd.zWaveProtocolVersion}"
    log.debug "zWaveProtocolSubVersion: ${cmd.zWaveProtocolSubVersion}"
}

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
	log.debug "BasicSet V1 ${cmd.inspect()}"
    def currentstate
    def motionstate
	if (cmd.value) {
		currentstate = "open"
        motionstate = "inactive"
	} else {
    	currentstate = "closed"
        motionstate = "active"
	}
    createEvent(name: "contact1", value: currentstate, descriptionText: "${device.displayName} is ${currentstate}")
    try {
        def childDevice = getChildDevices()?.find { it.deviceNetworkId == "${device.deviceNetworkId}-ep1"}
        if (childDevice)
        	childDevice.sendEvent(name: "motion", value: motionstate)
            childDevice.sendEvent(name: "contact", value: currentstate)
            log.debug "Fibaro is ${motionstate} and ${currentstate}"
    } catch (e) {
        log.error "Couldn't find child device, probably doesn't exist...? Error: ${e}"
    }
}

def zwaveEvent(physicalgraph.zwave.commands.multichannelv3.MultiChannelCmdEncap cmd) {
	log.debug "ZWaveEvent V3 ${cmd.inspect()}"
	def result
	if (cmd.commandClass == 32) {
        def currentstate
        def motionstate
		if (cmd.parameter == [0]) {
        	currentstate = "closed"
            motionstate = "active"
		}
		if (cmd.parameter == [255]) {
        	currentstate = "open"
            motionstate = "inactive"
		}
        log.debug "ep${cmd.sourceEndPoint} is ${currentstate}"
        //First update tile on this device
        sendEvent(name: "contact${cmd.sourceEndPoint}", value: currentstate, descriptionText: "$device.displayName - ep${cmd.sourceEndPoint} is ${currentstate}")
		//If not null then we have found either ep1 or ep2, hence try to send to the child device aswell
        try {
            def childDevice = getChildDevices()?.find { it.deviceNetworkId == "${device.deviceNetworkId}-ep${cmd.sourceEndPoint}"}
            if (childDevice)
                childDevice.sendEvent(name: "motion", value: motionstate)
                childDevice.sendEvent(name: "contact", value: currentstate)
        } catch (e) {
            log.error "Couldn't find child device, probably doesn't exist...? Error: ${e}"
        }
    }
	else if (cmd.commandClass == 49) {
		if ((cmd.sourceEndPoint >= 3) && (cmd.sourceEndPoint <= 6)) {
            
			def tempsensorid = cmd.sourceEndPoint - 2
			def tempendpoint = "temperature" + tempsensorid.toString()
			
            def tempval = ((cmd.parameter[4] * 256) + cmd.parameter[5])
            if (tempval > 32767) {
            	//Here we deal with negative values
            	tempval = tempval - 65536
            }
            //Finally round the temperature
            def tempprocessed = (tempval / 100).toDouble().round(1)
            
			//def cmdScale = cmd.scale == 1 ? "F" : "C"
			//def tempval = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmdScale, cmd.precision).toDouble().round(1)
            
            log.debug "${tempendpoint} has changed to ${tempprocessed}"
            
            sendEvent(name: tempendpoint, value: tempprocessed, displayed: true) //unit: getTemperatureScale()
            
			//If not null then we have found either contact1 or contact2, hence try to send to the child
            try {
                def childDevice = getChildDevices()?.find { it.deviceNetworkId == "${device.deviceNetworkId}-${tempendpoint}"}
                if (childDevice)
                	//We found a child device that matches so send it the new temperature
                    childDevice.sendEvent(name: "temperature", value: tempprocessed)
            } catch (e) {
            	//Not an error message here as people may not want child temperature devices
                log.debug "Couldn't find child ${tempendpoint} device, probably doesn't exist...? Error: ${e}"
            }
        }
	}
	else {
		//Send them here just in case we want to do more complicated processing (not doing it as need to have endpoint passed and that makes it a bit messy)
		def encapsulatedCommand = cmd.encapsulatedCommand([0x31: 2, 0x60: 3, 0x85: 2, 0x8E: 2, 0x72: 1, 0x70: 1, 0x86: 1, 0x7A: 1, 0xEF: 1, 0x2B: 1]) // can specify command class versions here like in zwave.parse
		log.debug ("Command from endpoint ${cmd.sourceEndPoint}: ${encapsulatedCommand}")
		if (encapsulatedCommand) {
			result = zwaveEvent(encapsulatedCommand)
		}
	}
    return result
}

def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv2.SensorMultilevelReport cmd)
{
	//This is no longer used as caught in an earlier event, but kept here in case the code is useful
	log.debug "Sensor MultiLevel Report - Sensor Type = ${cmd.sensorType}"
	switch (cmd.sensorType) {
		case 1:
			// temperature
			def cmdScale = cmd.scale == 1 ? "F" : "C"
			def tempval = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmdScale, cmd.precision).toDouble().round(1)
            sendEvent(name: "temperature1", value: tempval, displayed: false) //unit: getTemperatureScale()
			break;
	}
    log.debug map
	createEvent(map)
}

def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv1.SensorMultilevelReport cmd) {
    log.debug "SensorMultilevelReport $cmd"
}

def zwaveEvent(physicalgraph.zwave.Command cmd) {
	// This will capture any commands not handled by other instances of zwaveEvent
	// and is recommended for development so you can see every command the device sends
	log.debug "Catchall reached for cmd: ${cmd.toString()}}"
	return createEvent(descriptionText: "${device.displayName}: ${cmd}")
}

def updateCurrentParams() {
	log.debug "Sending configuration parameters to device"
    def cmds = []
	cmds << zwave.multiChannelAssociationV2.multiChannelAssociationSet(groupingIdentifier:2, nodeId:[zwaveHubNodeId]).format()
	cmds << zwave.associationV2.associationSet(groupingIdentifier:3, nodeId:[zwaveHubNodeId]).format()
	cmds << zwave.associationV1.associationRemove(groupingIdentifier:1, nodeId:zwaveHubNodeId).format()
	cmds << zwave.configurationV1.configurationSet(parameterNumber: 1, configurationValue:[param1.value]).format()
	cmds << zwave.configurationV1.configurationSet(parameterNumber: 2, configurationValue:[param2.value]).format()
	cmds << zwave.configurationV1.configurationSet(parameterNumber: 3, configurationValue:[param3.value]).format()
	cmds << zwave.configurationV1.configurationSet(parameterNumber: 4, configurationValue:[param4.value]).format()
	cmds << zwave.configurationV1.configurationSet(parameterNumber: 5, configurationValue:[param5.value]).format()
    cmds << zwave.configurationV1.configurationSet(parameterNumber: 6, configurationValue:[param6.value]).format()
	cmds << zwave.configurationV1.configurationSet(parameterNumber: 7, configurationValue:[param7.value]).format()
	cmds << zwave.configurationV1.configurationSet(parameterNumber: 8, configurationValue:[param8.value]).format()
	cmds << zwave.configurationV1.configurationSet(parameterNumber: 9, configurationValue:[param9.value]).format()
    cmds << zwave.configurationV1.configurationSet(parameterNumber: 10, configurationValue:[param10.value]).format()
    cmds << zwave.configurationV1.configurationSet(parameterNumber: 11, configurationValue:[param11.value]).format()
    cmds << zwave.configurationV1.configurationSet(parameterNumber: 12, configurationValue:[param12.value]).format()
	cmds << zwave.configurationV1.configurationSet(parameterNumber: 13, configurationValue:[param13.value]).format()
    cmds << zwave.configurationV1.configurationSet(parameterNumber: 14, configurationValue:[param14.value]).format()
	delayBetween(cmds, 500)
}
def listCurrentParams() {
	log.debug "Listing of current parameter settings of ${device.displayName}"
    def cmds = []
	cmds << zwave.multiChannelAssociationV2.multiChannelAssociationGet(groupingIdentifier:2).format()
	cmds << zwave.associationV2.associationGet(groupingIdentifier: 3).format()
	cmds << zwave.associationV1.associationGet(groupingIdentifier: 1).format()
	cmds << zwave.configurationV1.configurationGet(parameterNumber: 1).format()
	cmds << zwave.configurationV1.configurationGet(parameterNumber: 2).format()
   	cmds << zwave.configurationV1.configurationGet(parameterNumber: 3).format()
	cmds << zwave.configurationV1.configurationGet(parameterNumber: 4).format()
	cmds << zwave.configurationV1.configurationGet(parameterNumber: 5).format()
	cmds << zwave.configurationV1.configurationGet(parameterNumber: 6).format()
    cmds << zwave.configurationV1.configurationGet(parameterNumber: 7).format()
	cmds << zwave.configurationV1.configurationGet(parameterNumber: 8).format()
   	cmds << zwave.configurationV1.configurationGet(parameterNumber: 9).format()
	cmds << zwave.configurationV1.configurationGet(parameterNumber: 10).format()
	cmds << zwave.configurationV1.configurationGet(parameterNumber: 11).format()
   	cmds << zwave.configurationV1.configurationGet(parameterNumber: 12).format()
	cmds << zwave.configurationV1.configurationGet(parameterNumber: 13).format()
	cmds << zwave.configurationV1.configurationGet(parameterNumber: 14).format()
	delayBetween(cmds, 500)
}

def open1() {
    sendEvent(name: "contact1", value: "open", descriptionText: "$device.displayName (1) is opened manually")
    try {
        def childDevice = getChildDevices()?.find { it.deviceNetworkId == "${device.deviceNetworkId}-ep1"}
        log.debug "Changing child ${childDevice} to open/inactive"
        if (childDevice)
        	childDevice.sendEvent(name: "motion", value: "inactive")
            childDevice.sendEvent(name: "contact", value: "open")
    } catch (e) {
        log.error "Couldn't find child device, probably doesn't exist...? Error: ${e}"
    }
}

def close1() {
    sendEvent(name: "contact1", value: "closed", descriptionText: "$device.displayName (1) is closed manually")
    try {
        def childDevice = getChildDevices()?.find { it.deviceNetworkId == "${device.deviceNetworkId}-ep1"}
        log.debug "Changing child ${childDevice} to closed/active"
        if (childDevice)
        	childDevice.sendEvent(name: "motion", value: "active")
            childDevice.sendEvent(name: "contact", value: "closed")
    } catch (e) {
        log.error "Couldn't find child device, probably doesn't exist...? Error: ${e}"
    }
}

def open2() {
    sendEvent(name: "contact2", value: "open", descriptionText: "$device.displayName (2) is opened manually")
    try {
        def childDevice = getChildDevices()?.find { it.deviceNetworkId == "${device.deviceNetworkId}-ep2"}
        log.debug "Changing child ${childDevice} to open/inactive"
        if (childDevice)
        	childDevice.sendEvent(name: "motion", value: "inactive")
            childDevice.sendEvent(name: "contact", value: "open")
    } catch (e) {
        log.error "Couldn't find child device, probably doesn't exist...? Error: ${e}"
    }
}

def close2() {
    sendEvent(name: "contact2", value: "closed", descriptionText: "$device.displayName (2) is closed manually")
    try {
        def childDevice = getChildDevices()?.find { it.deviceNetworkId == "${device.deviceNetworkId}-ep2"}
        log.debug "Changing child ${childDevice} to closed/active"
        if (childDevice)
        	childDevice.sendEvent(name: "motion", value: "active")
			childDevice.sendEvent(name: "contact", value: "closed")
    } catch (e) {
        log.error "Couldn't find child device, probably doesn't exist...? Error: ${e}"
    }
}

def tempReadRequest() {
    def cmds = []
    runIn(30, "tempReadRequest")
    log.debug "tempReadRequest"
	cmds << response(encap(zwave.sensorMultilevelV3.sensorMultilevelGet(), 3))
	cmds << response(encap(zwave.sensorMultilevelV3.sensorMultilevelGet(), 4))
	cmds << response(encap(zwave.sensorMultilevelV3.sensorMultilevelGet(), 5))
	cmds << response(encap(zwave.sensorMultilevelV3.sensorMultilevelGet(), 6))
	sendHubCommand(cmds,1000)
}

private encap(cmd, endpoint = null) {
	if (cmd) {
		if (endpoint) {
			cmd = zwave.multiChannelV3.multiChannelCmdEncap(destinationEndPoint: endpoint).encapsulate(cmd)
		}

		if (zwaveInfo.zw.contains("s")) {
			zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
		} else {
			cmd.format()
		}
	}
}
1 Like

Your second version is working or not ? Because on my UBS this not work :frowning:

Thanks