Making progress - status so far - installed temp probes.
Much thanks to others for the DH and SA - I have only tweaked. Would be good to build all the functions of the Fibaro Universal Sensor into one DH and one SA but that is way beyond my skillset!
Part A – sort out the temperature probes
NOTE: THIS ASSUMES THAT YOU ARE USING CELSIUS TO RECORD YOUR TEMPERATURE READINGS. IF YOU ARE NOT, YOU MAY NEED TO CHANGE THE FORMULA IN THE DEVICE HANDLER TO GIVE YOU THE CORRECT RESULT. I WILL TRY TO CHECK THIS EVENTUALLY… ALSO NOTE THAT THE DOES NOT YET WORK WITH MINUS TEMPERATURES – AN EASY FIX JUST NOT YET DONE
Parts:
Fibaro universal sensor
12DC adaptor
4 x DS18B20 (http://www.ebay.co.uk/itm/111434870374 )
Step 1
A – removed ends of DC cable and soldered to PWR and GND of FUS (note: typically, wire with white strip on a DC adaptor is the positive wire which should join the PWR one)
B – soldered the four DS18B20 probes to the FUS (I had some spare wire which I soldered first to the FUS cables to extend them) – followed diagram4 at http://manuals.fibaro.com/content/manuals/en/FGBS-321/FGBS-321-EN-A-v1.00.pdf . You need to check the colour coding of your probes and match up with the manual. Ones I bought were red (VCC), black (GND and yellow (data)
C – should be ready to go – DO NOT TURN ON YET
Step 2 – link with SmartThings
A – go to add device (should automatically search)
B – turn on DC adaptor
C – press button on FUS three times relatively quickly
D – ST should recognise – call it what you want!
Step 3 – install custom device handler – note limitations above (possibly only Celsius and no negative temperatures)
A – login to IDE and install the following “from code” as a new device handler (apologies, I do not yet have a GH account – will set one up)
/**
* Device Type Definition File
*
* Device Type: Fibaro Universal Sensor - Dual Contact Sensor
* File Name: Fibaro Universal Sensor - Dual Contact Sensor.groovy
* Initial Release: 2016-01-17
* Author: Stuart Buchanan
* Modified: Paul Crookes 25-01-2016
* Further modified by others 19-01-2017
*
* Copyright 2016 Stuart Buchanan, based on original code by carlos.ir33 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 - Temperature sensors", namespace: "PukkaHQ", author: "Paul Crookes") {
capability "Contact Sensor"
capability "Temperature Measurement"
capability "Configuration"
attribute "temperature1", "number"
attribute "temperature2", "number"
attribute "temperature3", "number"
attribute "temperature4", "number"
command "listCurrentParams"
fingerprint deviceId: "0x2001", inClusters: "0x30 0x60 0x85 0x8E 0x72 0x70 0x86 0x7A 0xEF"
}
simulator {
}
tiles {
// Removed because I am not using these - you may wish to keep included
/* standardTile("contact1", "device.contact1", width: 1, height: 1) {
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: 1, height: 1) {
state "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#ffa81e"
state "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#79b821"
}*/
valueTile("temperature1", "device.temperature1", width: 1, height: 1) {
state("temperature", label:'${currentValue}°',
backgroundColors:[
[value: 31, color: "#153591"],
[value: 44, color: "#1e9cbb"],
[value: 59, color: "#90d2a7"],
[value: 74, color: "#44b621"],
[value: 84, color: "#f1d801"],
[value: 95, color: "#d04e00"],
[value: 96, color: "#bc2323"]
]
)
}
valueTile("temperature2", "device.temperature2", width: 1, height: 1) {
state("temperature", label:'${currentValue}°',
backgroundColors:[
[value: 31, color: "#153591"],
[value: 44, color: "#1e9cbb"],
[value: 59, color: "#90d2a7"],
[value: 74, color: "#44b621"],
[value: 84, color: "#f1d801"],
[value: 95, color: "#d04e00"],
[value: 96, color: "#bc2323"]
]
)
}
valueTile("temperature3", "device.temperature3", width: 1, height: 1) {
state("temperature", label:'${currentValue}°',
backgroundColors:[
[value: 31, color: "#153591"],
[value: 44, color: "#1e9cbb"],
[value: 59, color: "#90d2a7"],
[value: 74, color: "#44b621"],
[value: 84, color: "#f1d801"],
[value: 95, color: "#d04e00"],
[value: 96, color: "#bc2323"]
]
)
}
valueTile("temperature4", "device.temperature4", width: 1, height: 1) {
state("temperature", label:'${currentValue}°',
backgroundColors:[
[value: 31, color: "#153591"],
[value: 44, color: "#1e9cbb"],
[value: 59, color: "#90d2a7"],
[value: 74, color: "#44b621"],
[value: 84, color: "#f1d801"],
[value: 95, color: "#d04e00"],
[value: 96, color: "#bc2323"]
]
)
}
standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat") {
state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
}
main([ "temperature1", "temperature2", "temperature3", "temperature4"])
details(["contact1","contact2", "temperature1", "temperature2", "temperature3", "temperature4", "configure"])
}
}
def parse(String description) {
log.debug description
def result = null
def cmd = zwave.parse(description, [ 0x60: 3])
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 "configure"
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(configurationValue: [1], parameterNumber: 3, size: 1).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 4, size: 1).format()
delayBetween(cmds, 500)
}
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.multichannelv3.MultiChannelCmdEncap cmd) {
log.debug "ZWaveEvent V3 ${cmd.inspect()}"
def result
if (cmd.commandClass == 49) {
if (cmd.sourceEndPoint == 3) {
def brvalues = cmd.parameter
def TempCalc = ((brvalues[4] * 256) + brvalues[5]) / 100
log.debug TempCalc
log.debug "Temp1"
def map = [:]
map.value = TempCalc
map.displayed = true
map.name = "temperature1"
map.displayed = true
result = createEvent(map)
}
else
if (cmd.sourceEndPoint == 4) {
def brvalues = cmd.parameter
def TempCalc = ((brvalues[4] * 256) + brvalues[5]) / 100
def map = [:]
map.value = TempCalc
log.debug TempCalc
map.name = "temperature2"
map.displayed = true
result = createEvent(map)
log.debug "Temp1 (2)"
}
if (cmd.sourceEndPoint == 5) {
def brvalues = cmd.parameter
def TempCalc = ((brvalues[4] * 256) + brvalues[5]) / 100
def map = [:]
map.value = TempCalc
log.debug TempCalc
map.name = "temperature3"
map.displayed = true
result = createEvent(map)
log.debug "Temp1 (3)"
}
if (cmd.sourceEndPoint == 6) {
def brvalues = cmd.parameter
def TempCalc = ((brvalues[4] * 256) + brvalues[5]) / 100
def map = [:]
map.value = TempCalc
log.debug TempCalc
map.name = "temperature4"
map.displayed = true
result = createEvent(name: "temperature4", value: TempCalc, descriptionText: "Temperature", temperature: TempCalc, precision: 2, scale: 0, scaledSensorValue: TempCalc, sensorType: 1, sensorValue: brvalues, size: 4)
log.debug "Temp1 (4)"
}
}
if (cmd.commandClass == 32) {
if (cmd.parameter == [0]) {
if (cmd.sourceEndPoint == 1) {
result = createEvent(name: "contact1", value: "closed", descriptionText: "$device.displayName is closed")
log.debug "Contact1 is closed"
}
else
if (cmd.sourceEndPoint == 2) {
result = createEvent(name: "contact2", value: "closed", descriptionText: "$device.displayName is closed")
log.debug "Contact2 is closed"
}
}
if (cmd.parameter == [255]) {
if (cmd.sourceEndPoint == 1) {
result = createEvent(name: "contact1", value: "open", descriptionText: "$device.displayName is open")
log.debug "Contact1 is open"
}
else
if (cmd.sourceEndPoint == 2) {
result = createEvent(name: "contact2", value: "open", descriptionText: "$device.displayName is open")
log.debug "Contact2 is open"
}
}
}
return result
}
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
return createEvent(descriptionText: "${device.displayName}: ${cmd}")
}
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: 3).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 4).format()
delayBetween(cmds, 500)
}
B – go to devices and change the DH for the device you step up at step 2 to be this new custom one
Step 4 – create four “simulated temperature sensors”
A – go to “devices” in the IDE and create four new “simulated temperature sensors” – you can call these what you want
Step 5 – install the custom smartapp
A – login to IDE and install the following “from code” as a new device handler (again apologies, I do not yet have a GH account – will set one up)
/**
* Fibaro Universal Sensor App
*
* Copyright 2014 Joel Tamkin
*
* 2015-10-29: erocm123 - I removed the scheduled refreshes for my Philio PAN04 as it supports instant
* status updates with my custom device type
* 20016-01-25 PukkaHQ - Modified to work with Fibaro Universal Sensor
* 2017-01-19 Further modified by others to work with temperature sensors from the FUS - removed compatibility with FUS contacts
*
* 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.
*
*/
definition(
name: "Fibaro Univeral Sensor App",
namespace: "",
author: "Paul Crookes", // and others
description: "Associates Fibaro Universal Sensor 4 Temperature Probes with four SmartThings simulated temperature sensors",
category: "My Apps",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png")
preferences {
section("FUS Module:") {
input "fus", "capability.temperatureMeasurement", title: "Which FUS Module?", multiple: false, required: true
input "temperature1", "capability.temperatureMeasurement", title: "First temp probe?", multiple: false, required: true
input "temperature2", "capability.temperatureMeasurement", title: "Second temp probe?", multiple: false, required: true
input "temperature3", "capability.temperatureMeasurement", title: "Third temp probe?", multiple: false, required: true
input "temperature4", "capability.temperatureMeasurement", title: "Fourth temp probe?", multiple: false, required: true
}
}
def installed() {
log.debug "Installed with settings: ${settings}"
initialize()
}
def updated() {
log.debug "Updated with settings: ${settings}"
unsubscribe()
initialize()
}
/*def rsmHandler(evt) {
def t1 = 0
def t2 = 0
def t3 = 0
def t4 = 0
log.debug "FUS RsMHandler"
t1 = fus.currentValue("temperature1")
t2 = fus.currentValue("temperature2")
t3 = fus.currentValue("temperature3")
t4 = fus.currentValue("temperature4")
log.debug t1
log.debug t2
log.debug t3
log.debug t4
settings.temperature1.setTemperature(t1)
settings.temperature2.setTemperature(t2)
settings.temperature3.setTemperature(t3)
settings.temperature4.setTemperature(t4)
}*/
def rsmHandler1(evt) {
def t1 = 0
log.debug "FUS RsMHandler1"
t1 = fus.currentValue("temperature1")
log.debug t1
settings.temperature1.setTemperature(t1)
}
def rsmHandler2(evt) {
def t2 = 0
log.debug "FUS RsMHandler2"
t2 = fus.currentValue("temperature2")
log.debug t2
settings.temperature2.setTemperature(t2)
}
def rsmHandler3(evt) {
def t3 = 0
log.debug "FUS RsMHandler3"
t3 = fus.currentValue("temperature3")
log.debug t3
settings.temperature3.setTemperature(t3)
}
def rsmHandler4(evt) {
def t4 = 0
log.debug "FUS RsMHandler4"
t4 = fus.currentValue("temperature4")
log.debug t4
settings.temperature4.setTemperature(t4)
}
def initialize() {
subscribe(fus, "temperature1", rsmHandler1)
subscribe(fus, "temperature2", rsmHandler2)
subscribe(fus, "temperature3", rsmHandler3)
subscribe(fus, "temperature4", rsmHandler4)
/*These are for testing if events not triggering
runEvery5Minutes(testhandler("temperature1"))
schedule("23 20/2 * * * ?", testhandler ("temperature4"))
unschedule()*/
}
Step 6 – activate the smartapp
A – go to marketplace in the mobile app
B – go to the smartapp tab and click “my apps”
C – this should allow you to install the fibaro universal sensor app (the step 5 app) – click on it and set the FUS module to the name in step 2(D) and the temperature sensors should be the ones in step 4
D – fingers crossed – you should be ready to go. Once all installed, try grasping one probe at a time tightly and see if the temperature in the app updates – should do so relatively quickly
Part B – setting up the proportional–integral–derivative controller smartapp
Parts
A – To be continued…
Various other stainless steel bits and bobs
Thermowells x 3 (http://www.ebay.co.uk/itm/252560247341)