Here is the code I'm using.
/**
*
* 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.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format()
result << zwave.multiChannelV3.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.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format()
result << zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:2, commandClass:37, command:2).format()
response(delayBetween(result, 1000)) // returns the result of reponse()
}
def zwaveEvent(hubitat.zwave.commands.multichannelv3.MultiChannelCapabilityReport cmd)
{
log.debug "multichannelv3.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.multichannelv3.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.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format()
cmds << zwave.multiChannelV3.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.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format()
cmds << zwave.multiChannelV3.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.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:2, commandClass:37, command:2).format()
], 500)
}
def off() {
delayBetween([
zwave.switchAllV1.switchAllOff().format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:2, commandClass:37, command:2).format()
], 500)
}
def on1() {
delayBetween([
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:1, parameter:[255]).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format()
], 500)
}
def off1() {
delayBetween([
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:1, parameter:[0]).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format()
], 500)
}
def on2() {
delayBetween([
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:1, parameter:[255]).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:2).format()
], 500)
}
def off2() {
delayBetween([
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:1, parameter:[0]).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:2).format()
], 500)
}