Fibaro binary input (Dual contact and temperature sensor)


(Borristhecat) #1

I could do we some help finishing a device handler I have tweaked. What I want to be able to do is have 2 seperate Contact sensers, which I have but I want to declare them as two separate “enums” so that I can use them seperatly in webCoRE. At the moment I have it working, but only if I then create 2 seperate virtual contact sensers and link them to the device.

Credit to @fuzzysb Stuart Buchanan for creating the original DH, thanks

If anyone know how to do this and could give me some help, would really appreciate it :).

/**
 *  Device Type Definition File
 *
 *  Device Type:		Fibaro Universal Sensor - Dual Contact + Temp
 *  File Name:			Fibaro Universal Sensor - Dual Contact + Temp.groovy
 *	Initial Release:	2016-01-17
 *	Author:				Stuart Buchanan
 *  Modified:   Steven Stroud 10-06-2017
 *  
 *  Copyright 2017 Steven S, based on original code by Stuart Buchanan with thanks
 *
 *  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.
 *
 ***************************************************************************************
 */
metadata {
	definition (name: "Fibaro Universal Sensor - Dual Contact + Temp test", namespace: "Borristhecat", author: "Steven Stroud") {
    capability 	"Contact Sensor"
    capability 	"Contact Sensor" 
	capability 	"Temperature Measurement"
	capability 	"Configuration"
	capability 	"Sensor"
   
    
    command "updateCurrentParams"
    command "listCurrentParams"

        /* Capability notes
        0x30 Sensor Binary V1 V2
        0x60 Multi Channel V3
        0x85 Association V1 V2
        0x8E Multi Instance Association V1
        0x72 Manufacturer Specific V1 V2
        0x70 Configuration V1 V2
        0x86 Version V1
        0x7A Firmware Update Md V1 V2
        0xEF Mark V1
        0x2B Scene Activation V1
        */
	
	fingerprint deviceId: "0x2001", inClusters: "0x20 0x30 0x31 0x60 0x85 0x8E 0x72 0x70 0x86 0x7A 0xEF 0x2B"
	}

	simulator {
	}

	tiles(scale: 2) {
      	multiAttributeTile(name: "thermostat", type:"thermostat", width:6, height:4) {
			tileAttribute("device.temperature", key:"PRIMARY_CONTROL", canChangeIcon: true, canChangeBackground: true){
            	attributeState "default", label:'${currentValue}°', unit:"C", backgroundColor:"#fab907", icon:"st.Weather.weather2"
            }
			tileAttribute ("device.contact1", key: "SECONDARY_CONTROL") {
            	attributeState "open", label: '${name}'
				attributeState "closed", label: '${name}'
	}
			tileAttribute ("device.contact2", key: "TERTIARY_CONTROL") {
            	attributeState "open", label: '${name}'
				attributeState "closed", label: '${name}'
			}
    	}
       standardTile("contact1", "device.contact1", 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("contact2", "device.contact2", 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("configure", "device.configure", inactiveLabel: false, decoration: "flat", width: 2, height: 2 ) {
			state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
		}

	main(["thermostat"])
	details(["thermostat", "contact1" ,"contact2", "configure"])
	}
}

def parse(String description) {
	def result = null
	def cmd = zwave.parse(description, [ 0x20: 1, 0x30: 1, 0x31: 2, 0x60: 3, 0x85: 2, 0x8E: 2, 0x72: 1, 0x70: 1, 0x86: 1, 0x7A: 1, 0xEF: 1, 0x2B: 1 ])
	if (cmd) {
		result = zwaveEvent(cmd)
	}
	log.debug "parsed '$description' to result: ${result}"
	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 configure() {
	log.debug "Updating Configuration of ${device.displayName}"
    def cmds = []
    cmds << zwave.multiChannelAssociationV2.multiChannelAssociationSet(groupingIdentifier:2, nodeId:[zwaveHubNodeId]).format()
    cmds << zwave.associationV2.associationSet(groupingIdentifier:3, nodeId:[zwaveHubNodeId]).format()
    cmds << zwave.associationV2.associationRemove(groupingIdentifier:1, nodeId:[zwaveHubNodeId]).format()   
    cmds << zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 3, size: 1).format()
    cmds << zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 4, size: 1).format()
    cmds << zwave.configurationV1.configurationSet(configurationValue: [20], parameterNumber: 10, size: 1).format()
    cmds << zwave.configurationV1.configurationSet(configurationValue: [60], parameterNumber: 11, size: 1).format()
    cmds << zwave.configurationV1.configurationSet(configurationValue: [8], parameterNumber: 12, size: 1).format()
   
	delayBetween(cmds, 500)
}

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()}"
	if (cmd.value) {
	createEvent(name: "contact1", value: "open", descriptionText: "$device.displayName is open")
	} else {
	createEvent(name: "contact1", value: "closed", descriptionText: "$device.displayName is closed")
	}
}

def zwaveEvent(physicalgraph.zwave.commands.sensorbinaryv1.SensorBinaryReport cmd) {
    log.debug "Sensor Binary report"
	def map = [:]
	map.value = cmd.sensorValue ? "active" : "inactive"
	map.name = "motion"
	if (map.value == "active") {
		map.descriptionText = "$device.displayName detected motion"
	}
	else {
		map.descriptionText = "$device.displayName motion has stopped"
	}
	map
}


def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv2.SensorMultilevelReport cmd)
{
	log.debug "Sensor MultiLevel Report"
	def map = [:]
	switch (cmd.sensorType) {
		case 1:
			// temperature
			def cmdScale = cmd.scale == 1 ? "F" : "C"
			map.value = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmdScale, cmd.precision).toDouble().round(1)
            log.debug("tempvalue: " + map.value)
			map.unit = getTemperatureScale()
            log.debug("tempunit: " + map.unit)
			map.name = "temperature"
			break;
	}
	createEvent(map)
}

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


def createEvent(physicalgraph.zwave.commands.firmwareupdatemdv1.FirmwareMdReport cmd, Map item1) { 
    log.debug "checksum:       ${cmd.checksum}"
    log.debug "firmwareId:     ${cmd.firmwareId}"
    log.debug "manufacturerId: ${cmd.manufacturerId}"
}
 
def zwaveEvent(physicalgraph.zwave.commands.multichannelv3.MultiChannelCmdEncap cmd) {
    	log.debug "ZWaveEvent V3 ${cmd.inspect()}"
	if (cmd.commandClass == 32) {
		if (cmd.parameter == [0]) {
			if (cmd.sourceEndPoint == 1) {
				return createEvent(name: "contact1", value: "closed", descriptionText: "$device.displayName is closed", isStateChange: true)
				log.debug "Contact1 is closed"
			}
			else
			if (cmd.sourceEndPoint == 2) {
				return createEvent(name: "contact2", value: "closed", descriptionText: "$device.displayName is closed", isStateChange: true)
				log.debug "Contact2 is closed"
			}
		}
		if (cmd.parameter == [255]) {
			if (cmd.sourceEndPoint == 1) {
				return createEvent(name: "contact1", value: "open", descriptionText: "$device.displayName is open", isStateChange: true)
				log.debug "Contact1 is open"
			}
			else
			if (cmd.sourceEndPoint == 2) {
				return createEvent(name: "contact2", value: "open", descriptionText: "$device.displayName is open", isStateChange: true)
				log.debug "Contact2 is open"
			}
		}
    } else {
		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) {
			return zwaveEvent(encapsulatedCommand)
		}
	}
}

def zwaveEvent(physicalgraph.zwave.Command cmd) {
	log.debug "Catchall reached for cmd: ${cmd.toString()}}"
	[:]
}


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 updateCurrentParams() {
	log.debug "Updating current parameter settings of ${device.displayName}"
    def cmds = []
    cmds << zwave.multiChannelAssociationV2.multiChannelAssociationSet(groupingIdentifier:2, nodeId:[zwaveHubNodeId]).format()
    cmds << zwave.associationV2.associationSet(groupingIdentifier:3, nodeId:[zwaveHubNodeId]).format()
    cmds << zwave.associationV2.associationRemove(groupingIdentifier:1, nodeId:[zwaveHubNodeId]).format()   
    cmds << zwave.configurationV1.configurationSet(configurationValue: [0, 0], parameterNumber: 1, size: 2).format()
    cmds << zwave.configurationV1.configurationSet(configurationValue: [0, 0], parameterNumber: 2, size: 2).format()
    cmds << zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 3, size: 1).format()
    cmds << zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 4, size: 1).format()
    cmds << zwave.configurationV1.configurationSet(configurationValue: [255], parameterNumber: 5, size: 1).format()
    cmds << zwave.configurationV1.configurationSet(configurationValue: [255], parameterNumber: 6, size: 1).format()
    cmds << zwave.configurationV1.configurationSet(configurationValue: [255], parameterNumber: 7, size: 1).format()
    cmds << zwave.configurationV1.configurationSet(configurationValue: [255], parameterNumber: 8, size: 1).format()
    cmds << zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 9, size: 1).format()
    cmds << zwave.configurationV1.configurationSet(configurationValue: [120], parameterNumber: 10, size: 1).format()
    cmds << zwave.configurationV1.configurationSet(configurationValue: [200], parameterNumber: 11, size: 1).format()
    cmds << zwave.configurationV1.configurationSet(configurationValue: [8], parameterNumber: 12, size: 1).format()
    cmds << zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 13, size: 1).format()
    cmds << zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 14, size: 1).format()
   
	delayBetween(cmds, 500)
}

(Borristhecat) #2

@RobinWinbourne Is this something that you might be able to me help with?


(Robin) #3

Sorry… but veyond me I’m afraid.

You need to be looking at parent / child device types though… the parent creates two children which are linked.

This is a good example of a parent / child DTH:

@cjcharles may be able to help further.


(cjcharles) #4

@borristhecat
Is there a particular reason you dont want child devices? It would be easy to create child devices automatically (single click with no smartapp linking them) and solve the problem. Or you could even have a secondary value on the main DTH and then have a single child which has the secondary value as its main (and only) value.

The problem with trying to keep multiple values in a single DTH is that SmartThings is not built to handle it very well, and hence changes can easily break it. My experience is that if they are the same type you might get away with it, but if they are different (and youre trying to temperatures aswell) it is better to have some parts split out (also you can then do far more with them, from logging to a multitude of SmartApps that are built for single sensor devices.

I am not entirely sure what you have changed from the standard FUS DTH (which I am actually using). Can you paste it as code and then I can do a quick comparison since then formatting and everything is maintained.


(Borristhecat) #5

Yeah can do just don’t know how :frowning: :slight_smile: if you could let me know how to do it that would help, been trying to work it out for ages :joy:

I think the original DH was contact and PIR and I wanted two contacts, may have changed somthing on the temperature aswell but can’t remember now :thinking: .

The only reason was because I’m using them as simple latching switches then using webCoRE to decide what they do, I wanted to alow webCoRE to see both contacts in its attributes list. With the idea of then making the dash board neater.

Where as before when I was using it in ST standard apps you have to have separate devices. But didn’t realize this may cause issues. At the moment I’m using the same DH if I’m just using 2 contacts aswell as if I’m used temp and 2 contacts. So is it worth trying to do two separate ones?

Have this as the standard one with temp and contacts, then a dual contact one only?


(Robin) #6

I did away with my FUS sensors as I found them somewhat unreliable - missed events / getting stuck in the wrong state.

When I was using them the DTH was already two contacts, and I’ve never seen a DTH with temperature.


(cjcharles) #7

If you upload the code again in your first post (by editing it), just ensure that you use the ‘pre-formatted text’ button in the edit window. That will ensure that all the spacing and stuff is correctly preserved for me to check it.

I actually have a few temperature sensors which should turn up in the next couple of days, as soon as they arrive then I will give it a proper test with the DTH.

You’re right, the FUS sensors are a bit unreliable… they do sometimes miss an event, but because of how I use them it doesnt cause me any problems. I keep meaning to check a firmware update for them, as Im sure they must be aware of a problem and it is so easy to fix in their firmware…


(Borristhecat) #8

Remember @RobinWinbourne saying he had issues with then but touch wood mine haven’t missed a beat but like you said that may because of how I’m using them. Don’t think they would work well with a retractive switch :thinking: , but turning on and off osram ZigBee lamps and RGBW strip via webCoRE they have been great!


(Borristhecat) #9

BOOM thanks @cjcharles for that been trying to work that out for ages!


(cjcharles) #10

Thanks. Just done a comparison and it seems there are some strange sections of code in the DTH above that are either duplicated or not used, plus some bits where I will need to understand what certain parameters do!

If I have time over the weekend I’ll add temperature to my DTH and then split it out with child devices. You would then need to modify it a bit if you want something other than open/closed for each of the child devices.

As a side point, you say you are using it to control other lights, are you doing that with the relay outputs? Can they be zwave/ST/web controlled? I thought they were just a mirror of the input wires which need grounding to show closed…


(Borristhecat) #11

No I wish they were as I could control my LCM in my bathroom even better and have my DALI lights come on at different levels depending on conditions :slight_smile:. They are just a mirror of the input wires

No, I have pistons set up to turn on/ off the lights using the open/ closed trigger changing.


(Borristhecat) #12

how do you update the firmware on them? i thought it was only the z wave+ that you could do it on?


(cjcharles) #13

I didn’t mean doing the update necessarily, I thought I would try and see whether the update existed. After that I’d need to try and do it, probably involving moving the FUS to a separate Fibaro hub and then running the update there.


(Borristhecat) #14

Thought that needing a fibaro hub might be the case, if it was updatable :frowning:

If you ever find out if it’s possible let me know then will have to invest in one :slight_smile:


(Borristhecat) #15

@cjcharles tried to incorporate your Fibaro FGS-222 Double Relay DH to @Fuzzyligic Fibaro Universal Sensor- Contact/Motion so that it spits out the child devices, but i’m way out of my depth. Im able to tweak things, but I have no idea what’s going on in that DH :sweat_smile:


(Borristhecat) #16

Did you get any chance to look at this @cjcharles?


(cjcharles) #17

Sorry, had family around this weekend so didnt get a chance. Will do in the next couple of days.

Temperature sensors have just arrived aswell, so I can finally test with them added too.


(Borristhecat) #18

Brilliant :slight_smile: as I understand it they should work with multiple temperature sensors but I only use one per unit. Then using them for switches and door reed switches aswell as the temperature of every room :slight_smile:


(Borristhecat) #19

Hi @cjcharles any updates on this? did you get it working?


(Anon) #20

Hi,

Any updates on this ? I do not get it to work.

Thanks!