Floor Heating Thermostat (EU)

Sorry about that..... I stopped using my double channel one - here's the ported driver I used and if I remember correctly I used a virtual switch app with it... can't remember the name of it though.... might have been Eric Maycock's Simulated Switch driver.....

/**
 *  
 *	Fibaro FGS-222 Double Relay Switch Device Type - For use on Hubitat
 *  
 *	Author: Robin Winbourne
 *	Date: 2018-03-24 
 */
 
metadata {
definition (name: "Fibaro FGS-222 Double Relay Switch", namespace: "hubitat", author: "Robin Winbourne") {
capability "Switch"
capability "Relay Switch"
capability "Polling"
capability "Configuration"
capability "Refresh"
//capability "Zw Multichannel"

attribute "switch1", "string"
attribute "switch2", "string"

command "on1"
command "off1"
command "on2"
command "off2"
    
command "updateSingleParam" // This custom command can be used with Rule Machine or webCoRE, to send parameter values (paramNr & paramvalue) to the device

fingerprint deviceId: "0x1001", inClusters:"0x86, 0x72, 0x85, 0x60, 0x8E, 0x25, 0x20, 0x70, 0x27"

}
    
   preferences {
        input name: "param1", type: "enum", defaultValue: "255", required: true,
            title: "Parameter No. 1 - Activate / deactivate functions ALL ON / ALL OFF. Default value: 255.",
       		options: [
                    ["255" : "255 - ALL ON active, ALL OFF active"],
                    ["0" : "0 - ALL ON is not active ALL OFF is not active"],
                    ["1" : "1 - ALL ON is not active ALL OFF active"],
                    ["2" : "2 - ALL ON active ALL OFF is not active"]
                ]
       
        input name: "param3", type: "enum", defaultValue: "0", required: true,
            title: "Parameter No. 3 - Auto off relay after specified time, with the possibility of manual override - immediate Off after button push. Default value: 0.",
       		options: [
                    ["0" : "0 - Manual override disabled"],
                    ["1" : "1 - Manual override enabled"]
                ]

		input name: "param4", type: "number", range: "0..65535", defaultValue: "0", required: true,
            title: "Parameter No. 4 - Auto off for relay 1.  " +
                   "Available settings:\n" +
                   "[1 - 65535] (0,1 s – 6553,5 s) Time period for auto off, in miliseconds,\n" +
                   "0 - Auto off disabled.\n" +
                   "Default value: 0."

		input name: "param5", type: "number", range: "0..65535", defaultValue: "0", required: true,
            title: "Parameter No. 5 - Auto off for relay 2.  " +
                   "Available settings:\n" +
                   "[1 - 65535] (0,1 s – 6553,5 s) Time period for auto off, in miliseconds,\n" +
                   "0 - Auto off disabled.\n" +
                   "Default value: 0."

		input name: "param6", type: "enum", defaultValue: "0", required: true,
            title: "Parameter No. 6 - Sending commands to control devices assigned to 1st association group (key no. 1). " +
                   "NOTE: Parameter 15 value must be set to 1 to work properly. Default value: 0.",
       		options: [
                    ["0" : "0 - Commands are sent when device is turned on and off"],
                    ["1" : "1 - Commands are sent when device is turned off"],
                	["2" : "2 - Commands are sent when device is turned off"]
                ]

       		input name: "param7", type: "enum", defaultValue: "0", required: true,
            title: "Parameter No. 7 - Sending commands to control devices assigned to 2nd association group (key no. 2). " +
                   "NOTE: Parameter 15 value must be set to 1 to work properly. Default value: 0.",
       		options: [
                    ["0" : "0 - Commands are sent when device is turned on and off"],
                    ["1" : "1 - Commands are sent when device is turned off"],
                	["2" : "2 - Commands are sent when device is turned off"]
                ]

		input name: "param13", type: "enum", defaultValue: "0", required: true,
            title: "Parameter No. 13 - Assigns bistable key status to the device. Default value: 0.",
       		options: [
                    ["0" : "0 - Device changes status on key status change"],
                    ["1" : "1 - Device status depends on key status: ON when the key is ON"]
                ]

		input name: "param14", type: "enum", defaultValue: "1", required: true,
            title: "Parameter No. 14 - Switch type connector, you may choose between momentary and toggle switches. Default value: 1.",
       		options: [
                    ["0" : "0 - Momentary switch"],
                    ["1" : "1 - Toggle switch"]
                ]

		input name: "param15", type: "enum", defaultValue: "0", required: true,
            title: "Parameter No. 15 - Operation of the Dimmer and Roller Shutter Controller - enabling this option allows the user to dim lighting/shut roller by associating Dimmer/Roller Shutter Controller and holding or double press of double switch (only mono-stable switch). Default value: 0.",
       		options: [
                    ["0" : "0 - Dimmer/Roller Shutter Controller control is not active"],
                    ["1" : "1 - Dimmer/Roller Shutter Controller control is active"]
                ]

		input name: "param16", type: "enum", defaultValue: "1", required: true,
            title: "Parameter No. 16 - Saving the state of the device after a power failure. Default value: 1.",
       		options: [
                    ["0" : "0 - Switch returns to 'off' position"],
                    ["1" : "1 - Switch saves its state before power failure"]
                ]

        input name: "param30", type: "enum", defaultValue: "3", required: true,
            title: "Parameter No. 30 - Relay 1 - Response to General Alarm. Default value: 3.",
       		options: [
                    ["0" : "0 - Switch does not respond to alarm"],
                    ["1" : "1 - Switch turns on after detecting an alarm"],
                	["2" : "2 - Switch turns off after detecting an alarm"],
                	["3" : "3 - Switch flashes after detecting an alarm"]
                ]

     	input name: "param31", type: "enum", defaultValue: "2", required: true,
            title: "Parameter No. 31 - Relay 1 - Response to Flood Alarm. Default value: 2.",
       		options: [
                    ["0" : "0 - Switch does not respond to alarm"],
                    ["1" : "1 - Switch turns on after detecting an alarm"],
                	["2" : "2 - Switch turns off after detecting an alarm"],
                	["3" : "3 - Switch flashes after detecting an alarm"]
                ]
               
       input name: "param32", type: "enum", defaultValue: "3", required: true,
            title: "Parameter No. 32 - Relay 1 - Response to Smoke, CO, CO2 Alarm. Default value: 3.",
       		options: [
                    ["0" : "0 - Switch does not respond to alarm"],
                    ["1" : "1 - Switch turns on after detecting an alarm"],
                	["2" : "2 - Switch turns off after detecting an alarm"],
                	["3" : "3 - Switch flashes after detecting an alarm"]
                ]
       
       input name: "param33", type: "enum", defaultValue: "1", required: true,
            title: "Parameter No. 33 - Relay 1 - Response to Temperature Alarm. Default value: 1.",
       		options: [
                    ["0" : "0 - Switch does not respond to alarm"],
                    ["1" : "1 - Switch turns on after detecting an alarm"],
                	["2" : "2 - Switch turns off after detecting an alarm"],
                	["3" : "3 - Switch flashes after detecting an alarm"]
                ]

    	input name: "param40", type: "enum", defaultValue: "3", required: true,
            title: "Parameter No. 40 - Relay 2 - Response to General Alarm. Default value: 3.",
       		options: [
                    ["0" : "0 - Switch does not respond to alarm"],
                    ["1" : "1 - Switch turns on after detecting an alarm"],
                	["2" : "2 - Switch turns off after detecting an alarm"],
                	["3" : "3 - Switch flashes after detecting an alarm"]
                ]

     	input name: "param41", type: "enum", defaultValue: "2", required: true,
            title: "Parameter No. 41 - Relay 2 - Response to Flood Alarm. Default value: 2.",
       		options: [
                    ["0" : "0 - Switch does not respond to alarm"],
                    ["1" : "1 - Switch turns on after detecting an alarm"],
                	["2" : "2 - Switch turns off after detecting an alarm"],
                	["3" : "3 - Switch flashes after detecting an alarm"]
                ]
               
       input name: "param42", type: "enum", defaultValue: "3", required: true,
            title: "Parameter No. 42 - Relay 2 - Response to Smoke, CO, CO2 Alarm. Default value: 3.",
       		options: [
                    ["0" : "0 - Switch does not respond to alarm"],
                    ["1" : "1 - Switch turns on after detecting an alarm"],
                	["2" : "2 - Switch turns off after detecting an alarm"],
                	["3" : "3 - Switch flashes after detecting an alarm"]
                ]
       
       input name: "param43", type: "enum", defaultValue: "1", required: true,
            title: "Parameter No. 43 - Relay 2 - Response to Temperature Alarm. Default value: 1.",
       		options: [
                    ["0" : "0 - Switch does not respond to alarm"],
                    ["1" : "1 - Switch turns on after detecting an alarm"],
                	["2" : "2 - Switch turns off after detecting an alarm"],
                	["3" : "3 - Switch flashes after detecting an alarm"]
                ]

		input name: "param39", type: "number", range: "0..65535", defaultValue: "600", required: true,
            title: "Parameter No. 39 - Active flashing alarm time. " +
            	   "This parameter allows to set time parameter used in timed modes.\n" +
                   "Available settings:\n" +
                   "[1-65535][ms].\n" +
                   "Default value: 600."
       
    input name: "paramAssociationGroup1", type: "bool", defaultValue: true, required: true,
             title: "The Fibaro Sigle Switch provides the association of three groups.\n\n" +
                    "1st group is assigned to key no. 1.\n" +
                    "Default value: true"

        input name: "paramAssociationGroup2", type: "bool", defaultValue: true, required: true,
             title: "2nd group is assigned to key no. 2.\n" +
                    "Default value: true"

        input name: "paramAssociationGroup3", type: "bool", defaultValue: false, required: true,
             title: "3rd group reports state of devices. Only one device can be associated to this group.\n" +
                    "Default value: false"
    }
}

def parse(String description) {
    def result = []
    def cmd = zwave.parse(description)
    if (cmd) {
        result += zwaveEvent(cmd)
        log.debug "Parsed ${cmd} to ${result.inspect()}"
    } else {
        log.debug "Non-parsed event: ${description}"
    }
    return result
}


def zwaveEvent(hubitat.zwave.commands.basicv1.BasicSet cmd) {
	sendEvent(name: "switch", value: cmd.value ? "on" : "off", type: "digital")
    def result = []
    result << zwave.multiChannelV4.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format()
    result << zwave.multiChannelV4.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:2, commandClass:37, command:2).format()
    response(delayBetween(result, 1000)) // returns the result of reponse()
}

def zwaveEvent(hubitat.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd)
{
    sendEvent(name: "switch", value: cmd.value ? "on" : "off", type: "digital")
    def result = []
    result << zwave.multiChannelV4.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format()
    result << zwave.multiChannelV4.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:2, commandClass:37, command:2).format()
    response(delayBetween(result, 1000)) // returns the result of reponse()
}


def zwaveEvent(hubitat.zwave.commands.multichannelv4.MultiChannelCapabilityReport cmd) 
{
    log.debug "multichannelv4.MultiChannelCapabilityReport $cmd"
    if (cmd.endPoint == 2 ) {
        def currstate = device.currentState("switch2").getValue()
        if (currstate == "on")
        	sendEvent(name: "switch2", value: "off", isStateChange: true, display: false)
        else if (currstate == "off")
        	sendEvent(name: "switch2", value: "on", isStateChange: true, display: false)
    }
    else if (cmd.endPoint == 1 ) {
        def currstate = device.currentState("switch1").getValue()
        if (currstate == "on")
        sendEvent(name: "switch1", value: "off", isStateChange: true, display: false)
        else if (currstate == "off")
        sendEvent(name: "switch1", value: "on", isStateChange: true, display: false)
    }
}

def zwaveEvent(hubitat.zwave.commands.multichannelv4.MultiChannelCmdEncap cmd) {
   def map = [ name: "switch$cmd.sourceEndPoint" ]
    
   switch(cmd.commandClass) {
      case 32:
         if (cmd.parameter == [0]) {
            map.value = "off"
         }
         if (cmd.parameter == [255]) {
            map.value = "on"
         }
         createEvent(map)
         break
      case 37:
         if (cmd.parameter == [0]) {
            map.value = "off"
         }
         if (cmd.parameter == [255]) {
            map.value = "on"
         }
         break
    }
    def events = [createEvent(map)]
    if (map.value == "on") {
            events += [createEvent([name: "switch", value: "on"])]
    } else {
         def allOff = true
         (1..2).each { n ->
             if (n != cmd.sourceEndPoint) {
                 if (device.currentState("switch${n}").value != "off") allOff = false
             }
         }
         if (allOff) {
             events += [createEvent([name: "switch", value: "off"])]
         }
    }
    events
}

def zwaveEvent(hubitat.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
    return createEvent(descriptionText: "${device.displayName}: ${cmd}")
}

def zwaveEvent(hubitat.zwave.commands.switchallv1.SwitchAllReport cmd) {
   log.debug "SwitchAllReport $cmd"
}

def refresh() {
	def cmds = []
    cmds << zwave.manufacturerSpecificV2.manufacturerSpecificGet().format()
	cmds << zwave.multiChannelV4.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format()
    cmds << zwave.multiChannelV4.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:2, commandClass:37, command:2).format()
	delayBetween(cmds, 1000)
}

def zwaveEvent(hubitat.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
	def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
	log.debug "msr: $msr"
    updateDataValue("MSR", msr)
}

def poll() {
	def cmds = []
	cmds << zwave.multiChannelV4.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format()
    cmds << zwave.multiChannelV4.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:2, commandClass:37, command:2).format()
	delayBetween(cmds, 1000)
}

def configure() {
	log.debug "Executing 'configure'"
    delayBetween([
          zwave.configurationV1.configurationSet(parameterNumber:1, configurationValue:[param1.value]).format(),
          zwave.configurationV1.configurationSet(parameterNumber:3, configurationValue:[param3.value]).format(),
          zwave.configurationV1.configurationSet(parameterNumber:4, configurationValue:[param4.value]).format(),
          zwave.configurationV1.configurationSet(parameterNumber:5, configurationValue:[param5.value]).format(),
          zwave.configurationV1.configurationSet(parameterNumber:6, configurationValue:[param6.value]).format(),
          zwave.configurationV1.configurationSet(parameterNumber:7, configurationValue:[param7.value]).format(),
          zwave.configurationV1.configurationSet(parameterNumber:13, configurationValue:[param13.value]).format(),
          zwave.configurationV1.configurationSet(parameterNumber:14, configurationValue:[param14.value]).format(),
          zwave.configurationV1.configurationSet(parameterNumber:15, configurationValue:[param15.value]).format(),
          zwave.configurationV1.configurationSet(parameterNumber:16, configurationValue:[param16.value]).format(),
          zwave.configurationV1.configurationSet(parameterNumber:30, configurationValue:[param30.value]).format(),
          zwave.configurationV1.configurationSet(parameterNumber:31, configurationValue:[param31.value]).format(),
          zwave.configurationV1.configurationSet(parameterNumber:32, configurationValue:[param32.value]).format(),
          zwave.configurationV1.configurationSet(parameterNumber:33, configurationValue:[param33.value]).format(),
          zwave.configurationV1.configurationSet(parameterNumber:39, configurationValue:[param39.value]).format(),
          zwave.configurationV1.configurationSet(parameterNumber:40, configurationValue:[param40.value]).format(),
          zwave.configurationV1.configurationSet(parameterNumber:41, configurationValue:[param41.value]).format(),
          zwave.configurationV1.configurationSet(parameterNumber:42, configurationValue:[param42.value]).format(),
          zwave.configurationV1.configurationSet(parameterNumber:43, configurationValue:[param43.value]).format(),
          zwave.associationV2.associationSet(groupingIdentifier:1, nodeId:[zwaveHubNodeId]).format(),
          zwave.associationV2.associationSet(groupingIdentifier:2, nodeId:[zwaveHubNodeId]).format(),
          zwave.associationV2.associationSet(groupingIdentifier:3, nodeId:[zwaveHubNodeId]).format(),
    ])  
}

def updateSingleparam(paramNum, paramValue) {
	log.debug "Updating single Parameter (paramNum: $paramNum, paramValue: $paramValue)"
    	zwave.configurationV1.configurationSet(parameterNumber: paramNum, ConfigurationValue: paramValue)
}

/**
* Triggered when Save button is pushed on Preference UI
*/
def updated()
{
	log.debug "Preferences have been changed. Attempting configure()"
    def cmds = configure()
    response(cmds)
}
def on() { 
   delayBetween([
        zwave.switchAllV1.switchAllOn().format(),
        zwave.multiChannelV4.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format(),
        zwave.multiChannelV4.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:2, commandClass:37, command:2).format()
    ], 500)
}
def off() {
   delayBetween([
        zwave.switchAllV1.switchAllOff().format(),
        zwave.multiChannelV4.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format(),
        zwave.multiChannelV4.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:2, commandClass:37, command:2).format()
    ], 500)
}

def on1() {
    delayBetween([
        zwave.multiChannelV4.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:1, parameter:[255]).format(),
        zwave.multiChannelV4.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format()
    ], 500)
}

def off1() {
    delayBetween([
        zwave.multiChannelV4.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:1, parameter:[0]).format(),
        zwave.multiChannelV4.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format()
    ], 500)
}

def on2() {
    delayBetween([
        zwave.multiChannelV4.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:1, parameter:[255]).format(),
        zwave.multiChannelV4.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:2).format()
    ], 500)
}

def off2() {
    delayBetween([
        zwave.multiChannelV4.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:1, parameter:[0]).format(),
        zwave.multiChannelV4.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:2).format()
    ], 500)
}