'Fibaro Z-Wave FGK-101 Temperature & Door/Window Sensor' Full Support Handler

The Fibaro FGK-101 Temperature & Door/Window sensor goes on sale in the US this month (908.4 MHz version) :

At this time, SmartThings built-in support for Fibaro FGK-101 is fairly basic : just open/closed.
But this Z-Wave device offers much more than that : temperature measurement, tampering alarm and a set of configurable options.

AFAIK, it is the smallest available Z-Wave temperature sensor (76 x 17 x 19 mm = 3" x 2/3" x 3/5") and a very accurate one : the optional TO92 DS18B20 sensor is +/-0.5°C accurate from –10°C to +85°C (14°F to 185°F) according to the Dallas/Maxim DS18B20 datasheet :
http://pdf.datasheetcatalog.com/datasheet/maxim/DS18B20.pdf.

Although still a “work in progress”, the Handler below supports periodic and threshold controlled Temperature measurements, anti-Tampering Alarm as well as Open/Closed sensing and it can be configured, modifying some lines in the Handler, for different behaviors (like reporting in °F instead of °C or changing the wake-up period from the default 60mn).

Since it is my first attempt at a ST Handler, I am pretty sure it is sub-optimal, but some of you may find it useful.
Any comments (or bug reports !) welcomed :slight_smile:

    /**
 *  Fibaro Z-Wave FGK-101 Temperature & Door/Window Sensor Handler [v0.8.1, 17 December 2014]
 *        
 *  Copyright 2014 Jean-Jacques GUILLEMAUD
 *
 *  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.
 *
 */
 
/******************************************************************************************************************************
 *    Fibaro Z-Wave FGK-101 Marketing Description is at :
 *        http://www.fibaro.com/en/the-fibaro-system/door-window-sensor
 *
 *  Fibaro FGK-10x Operating Manual can be downloaded at :
 *        http://www.fibaro.com/files/instrukcje/eng/DoorWindowSensor%20FGK-101-107%20ENG_v21-v23.pdf
 *
 *    The current version of this Handler is parameterized to force Device's wakeup :
 *        - on any open<->closed state change
 *        - in case of Tampering Alarm triggering
 *        - every 60mn (wakeUpIntervalSet(seconds:60*60), hard coded)
 *        - whenever Temperature delta change since last report is greater than 0.31°C (Parameter#12, hard coded)
 *        also :
 *        - Temperature is natively reported by sensor in Celsius (SensorMultilevelReport[scale:0]);
 *          convertion is needed for Fahrenheit display 
 *
 *  A few specificities of this device that are relevant to better understand some parts of this Handler :
 *        - it is a battery operated device, so Commands can only be sent to it whenever it wakes up
 *        - it is a multi-channel Device, and the multi-level temperature sensor reports only from EndPoint#2
 *        - specific configurable parameters are documented in the above Operating Manual
 *        - some of those parameters must be modified to activate the anti-Tampering Alarm
 *        - some of the "scaffolding" has been left in place as comments, since it may help other people to understand/modify this Handler
 *        - BEWARE : the optional DS18B20 sensor must be connected BEFORE the Device is activated (otherwise, reset the Device)
 *        - IMPORTANT : for debugging purpose, it is much better to change the wake-up period from the default 60mn to 1mn or so;
 *                    but unless you force the early wake up of the sensor (forcing open/closed for instance), you will have to
 *                    wait up to 60mn for the new value to become effective.
 *
 * Z-Wave Device Class: GENERIC_TYPE_SENSOR_BINARY / SPECIFIC_TYPE_ROUTING_SENSOR_BINARY
 * FGK-101 Raw Description [EndPoint:0] : "0 0 0x2001 0 0 0 c 0x30 0x9C 0x60 0x85 0x72 0x70 0x86 0x80 0x84 0x7A 0xEF 0x2B"
 * Command Classes supported according to Z-Wave Certificate ZC08-14070004 for FGK-101\US :
 *     Used in Handler :
 *        - 0x20 - 32  : BASIC                    V1
 *          0x30 - 48  : SENSOR_BINARY            V1 !V2!
 *        - 0x31 - 49  : SENSOR_MULTILEVEL        V1 !V2! V3 V4 V5
 *          0x60 - 96  : MULTI_CHANNEL            V3
 *          0x70 - 112 : CONFIGURATION            V1 !V2!
 *          0x72 - 114 : MANUFACTURER_SPECIFIC     V1 !V2!
 *          0x80 - 128 : BATTERY                    V1
 *          0x84 - 132 : WAKE_UP                    !V1! V2
 *          0x85 - 133 : ASSOCIATION                V1 !V2!
 *          0x9C - 156 : SENSOR_ALARM                V1
 *    NOT used in Handler :
 *          0x2B - 43  : SCENE_ACTIVATION            V1    
 *        - 0x56 - 86  : CRC_16_ENCAP                V1
 *          0x86 - 134 : VERSION                    V1
 *
 *     also found in FGK-101 Raw Description, in addition to Z-Wave Certificate for FGK-101\US [?!!] :
 *        + 0x7A - 122 : FIRMWARE_UPDATE_MD        V1 V2
 *        + 0xEF - 239 : MARK                      V1
 ******************************************************************************************************************************/

/******************************************************************************************************************************
 *    List of Known Bugs / Oddities / Missing Features :
 *        - valueTitle does not show displayNames on mobile Dashboard/Things page;
 *          attempted workaround using : valueTile(){unit:'${displayName}') failed
 *        - valueTile behaves differently on mobile Dashboard (interpolated colors) from Simulator (step-wise colors)
 *        - using Preferences values instead of hard-coded values for some parameters would be nicer
 *****************************************************************************************************************************/

metadata {
    definition (name: "JJ's Fibaro FGK-101 Handler", namespace: "JJG2014", author: "Jean-Jacques GUILLEMAUD") {
        capability "Contact Sensor"
        capability "Battery"
        capability "Configuration"
        capability "Temperature Measurement"
        capability "Sensor"
        capability "Alarm"

        // FGK-101 Raw Description [EndPoint:0] : "0 0 0x2001 0 0 0 c 0x30 0x9C 0x60 0x85 0x72 0x70 0x86 0x80 0x84 0x7A 0xEF 0x2B"
        fingerprint deviceId: "0x2001", inClusters: "0x30, 0x60, 0x70, 0x72, 0x80, 0x84, 0x85, 0x9C"  // should include "0x20, 0x31" too ?!!
    }

    simulator {
        status "open":  "command: 2001, payload: FF"
        status "closed": "command: 2001, payload: 00"

        def T_values=[10,14,14.9,15,17,17.9,18,19,19.9,20,22,22.9,23,24,44,44.9,45,46,100]
        def float Ti
        for (int i = 0; i <= T_values.size()-1; i += 1) {
            Ti=T_values.get(i)
            def theSensorValue = [(short)0, (short)0, (short)(Ti*100)/256, (short)(Ti*100)%256]
            status "temperature ${Ti}°C":  zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2).encapsulate(zwave.sensorMultilevelV2.sensorMultilevelReport(scaledSensorValue: i, precision: 2, scale: 0, sensorType: 1, sensorValue: theSensorValue, size:4)).incomingMessage()
        }
    }

    tiles {
        valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2, canChangeIcon: true, canChangeBackground: true) {
            // label:'${name}', label:'${currentValue}', unit:"XXX" work, but NOT label:'${device.name}', label:'${displayName}', unit:'${unit}', ...
            state "temperature", label:'${currentValue}°C', /* unit:'${unit}', */ icon: "st.alarm.temperature.normal",
            // redondant lines added to avoid color interpolation on Dashboard (a feature or a bug ?!)
            backgroundColors:[                            // ***on IDE Simulator***        // ***on iPad App***
                [value: 14, color: "#0033ff"],            //     °C <=14 : dark blue        //     °C <=14    : dark blue 
                    //[value: 14.1, color: "#00ccff"],    <- decimal value IGNORED by the Tile !!!
                    //[value: 14.5],                    // 15< °C <=19 : light blue        // 14< °C <15    : interpolated dark blue<-> light blue
                    [value: 15, color: "#00ccff"],        // 16< °C <=19 : light blue        // 15<=°C <=19    : light blue
                [value: 17, color: "#00ccff"],            // 16< °C <=19 : light blue        // 15<=°C <=19    : light blue
                    //[value: 17.5],                    // 15< °C <=19 : light blue        // 14< °C <15    : interpolated light blue<->blue-green
                    [value: 18, color: "#ccffcc"],        // 15< °C <=19 : light blue        // 18<=°C <=19    : blue-green
                [value: 19, color: "#ccffcc"],            // 15< °C <=19 : light blue        // 19°C            : blue-green
                    //[value: 19.5],                    // 19< °C <=21 : blue-green        // 19< °C <20    : interpolated blue-green<->green
                    [value: 20, color: "#ccff00"],        // 19< °C <=21 : blue-green        // 20<=°C <=21    : green
                [value: 22, color: "#ccff00"],            // 21< °C <=23 : green            // 22°C            : green
                    //[value: 22.5],                    // 23< °C <=45 : orange            // 22< °C <23    : interpolated green<-> orange
                    [value: 23, color: "#ffcc33"],        // 23< °C <=45 : orange          // 23<=°C <=44    : orange
                [value: 43, color: "#ffcc33"],            // 23< °C <=45 : orange          // 44°C            : orange
                    //[value: 43.5],                    // 45< °C      : red            // 44< °C <45    : interpolated orange <-> red
                       [value: 44, color: "#ff3300"]        // 45< °C      : red              // 45<=°C        : red
            ]
        }
        
        standardTile("contact", "device.contact") {
            state "open", label: 'ouvert'/* in English :'${name}' */, icon: "st.contact.contact.open", backgroundColor: "#ffa81e"
            state "closed", label: 'fermé'/* in English :'${linkText}' */, icon: "st.contact.contact.closed", backgroundColor: "#79b821"
        }
        
        valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
            state "battery", label:'pile @ ${currentValue}%' /*battery*/, unit:""
        } 
        
        main(["temperature"])
        details(["temperature", "contact", "battery"])
    }
}

////////////////////////////////
// parse events into attributes
////////////////////////////////

def parse(String description) {
        state.parseCount=state.parseCount+1
        settings.debugLevel = 2        // set to 1 or 2 when experimenting
        if (debugLevel>=1) {log.debug "--------------------------Parsing... ; state.parseCount: ${state.parseCount}--------------------------"}
        if (debugLevel>=2) {log.debug "Parsing... '${description}'"}
        def result = null
        def cmd = zwave.parse(description, [0x20:1, 0x30:2, 0x31:2, 0x60:3, 0x70:2, 0x72:2, 0x80:1, 0x84:1, 0x85:2, 0x9C:1])
        if (cmd) {
                result = zwaveEvent(cmd)
                if (debugLevel>=1) {log.debug "Parsed ${cmd} to ${result.inspect()}"}
        } else {
                log.debug "Non-parsed event: ${description}"
        }
        return result
}

def wakeUpResponse(cmdBlock) {
    //Initialization... (executed only once, when the Handler has been updated)
    //All untouched parameters are supposed to be DEFAULT (as factory-set)
    if (state.isInitialized == false) {
        if (debugLevel>=2) {log.debug "state.isInitialized : ${state.isInitialized}"}
        cmdBlock << zwave.wakeUpV1.wakeUpIntervalSet(seconds:60*60, nodeid:zwaveHubNodeId).format() // NB : may have to wait 30mn for that value to be refreshed !
        cmdBlock << "delay 1200"
        // NOTE : any asynchronous temperature query thru SensorMultilevelGet() does NOT reset the delta-Temp base value (managed by DS18B20 hardware)
        cmdBlock << zwave.configurationV2.configurationSet(parameterNumber: 12/*for FGK101*/, size: 1, configurationValue: [5]/* 5/16=0.31°C */).format() 
        cmdBlock << "delay 1200"     
        // inclusion of Device in Association#3 is needed to get delta-Temperature notification messages [cf Parameter#12 above]
        cmdBlock << zwave.associationV2.associationSet(groupingIdentifier:3, nodeId:[zwaveHubNodeId]).format()
        cmdBlock << "delay 1200"
        // inclusion of Device in Association#2 is needed to enable SensorAlarmReport() Command [anti-Tampering protection]
        cmdBlock << zwave.associationV2.associationSet(groupingIdentifier:2, nodeId:[zwaveHubNodeId]).format()
        cmdBlock << "delay 1200"
        state.isInitialized = true
        if (debugLevel>=2) {log.debug "state.isInitialized : ${state.isInitialized}"}
    }
    
    //Regular Commands...
        def nowTime = new Date().time
        if (nowTime-state.lastReportBattery > state.batteryInterval) {
            cmdBlock << zwave.batteryV1.batteryGet().format()
            cmdBlock << "delay 1200"
        }
        //next 2 lines redondant since any open/closed status change is asynchronously notified
        //cmdBlock << zwave.basicV1.basicGet().format()
        //cmdBlock << "delay 1200"
        //next 2 lines redondant too : SensorBinaryReport(EndPoint: 1) == BasicReport
        //cmdBlock << zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint: 1, destinationEndPoint: 1, commandClass:0x30 /*Sensor Binary*/, command:2).format()
        //cmdBlock << "delay 1200"
        //cmdBlock << zwave.sensorAlarmV1.sensorAlarmGet().format()
        //cmdBlock << "delay 1200"
        //cmdBlock << zwave.multiChannelV3.multiChannelEndPointGet().format()                // MultiChannelEndPointReport  -> dynamic: false, endPoints: 2
        //cmdBlock << "delay 1200"
        //cmdBlock << zwave.multiChannelV3.multiChannelCapabilityGet(endPoint:1).format()    // MultiChannelCapabilityReport -> commandClass: [48], dynamic: false, endPoint: 1, genericDeviceClass: 32, specificDeviceClass: 1
        //cmdBlock << "delay 1200"
        //cmdBlock << zwave.multiChannelV3.multiChannelCapabilityGet(endPoint:2).format()    // MultiChannelCapabilityReport -> commandClass: [49], dynamic: false, endPoint: 2, genericDeviceClass: 33, specificDeviceClass: 1
        //cmdBlock << "delay 1200"
        cmdBlock << zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint: 2, destinationEndPoint: 2, commandClass:0x31/*Sensor Multilevel*/, command:4/*Get*/).format()
        cmdBlock << "delay 1200"
        cmdBlock << zwave.wakeUpV1.wakeUpNoMoreInformation().format()
        if (debugLevel>=2) {log.debug "wakeUpNoMoreInformation()"}
        return cmdBlock
}

def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd) {
        if (debugLevel>=2) {log.debug "wakeupv1.WakeUpNotification $cmd"}
        def event = createEvent(descriptionText: "${device.displayName} woke up", isStateChange: true, displayed: false)
        def cmdBlock =[]
        cmdBlock=wakeUpResponse(cmdBlock)
        return [event, response(cmdBlock)]
}

def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv2.SensorMultilevelReport cmd) {
        // Real-time clock of sensors (ceramic resonator) is up to 3% inaccurate
        def final long maxEventInterval = (4*60*60-10*60)*1000  // at least 1 Temperature Report event every 4 hours
        def float scaledSensorValue = cmd.scaledSensorValue
        // Adjust measured temperature based on previous calibration
        switch (device.name) {
            case 'T005' :                                        //FSU    
                scaledSensorValue = scaledSensorValue + 0.0709
                log.debug "Temp Adjust for : ${device.name}"
                break;
            case 'T006' :                                        //MLE
                scaledSensorValue = scaledSensorValue + 0.0452
                log.debug "Temp Adjust for : ${device.name}"
                break;
            case 'T001' :                                        //JJG
                scaledSensorValue = scaledSensorValue - 0.0448
                log.debug "Temp Adjust for : ${device.name}"
                break;
            case 'T003' :                                        //MPT
                scaledSensorValue = scaledSensorValue - 0.0448
                log.debug "Temp Adjust for : ${device.name}"
                break;
            case 'T002' :                                        //NBN    
                scaledSensorValue = scaledSensorValue - 0.0603
                log.debug "Temp Adjust for : ${device.name}"
                break;
            case 'T004' :                                        //SCU
                scaledSensorValue = scaledSensorValue + 0.0166
                log.debug "Temp Adjust for : ${device.name}"
                break;
        }
        def float ftemp = (((int) (scaledSensorValue*100+5)/10)*1.0)/10
        def nowTime = new Date().time
        if (debugLevel>=2) {
            log.debug "cmd.scaledSensorValue : ${cmd.scaledSensorValue}"
            log.debug "correction : ${scaledSensorValue-cmd.scaledSensorValue}"
            log.debug "device.displayName : ${device.displayName}"
            log.debug "'Date().time' : ${new Date().time}"
            log.debug "state.forcedWakeUp : ${state.forcedWakeUp}"
            log.debug "maxEventInterval : ${maxEventInterval}"
            log.debug "state.lastReportTime : ${state.lastReportTime}"
            log.debug "nowTime : ${nowTime}"
            log.debug "(nowTime-state.lastReportTime > maxEventInterval) : ${(nowTime-state.lastReportTime > maxEventInterval)}"
            log.debug "ftemp : ${ftemp}"
            log.debug "state.lastReportedTemp: ${state.lastReportedTemp}"
            log.debug "((ftemp-state.lastReportedTemp).abs()>0.25): ${(ftemp-state.lastReportedTemp).abs()>0.299}"
        }
        if (((ftemp-state.lastReportedTemp).abs()>0.299) | (nowTime-state.lastReportTime > maxEventInterval) | state.forcedWakeUp) {
            def map = [ displayed: true, value: ftemp.toString(), isStateChange:true, linkText:"${device.displayName}" ]
            switch (cmd.sensorType) {
                case 1:
                        map.name = "temperature"
                        map.unit = cmd.scale == 1 ? "F" : "C"
                        break;
            }
            if (debugLevel>=2) {
                log.debug "temperature Command : ${map.inspect()}"
            }
            state.lastReportedTemp = ftemp
            state.lastReportTime = nowTime
            state.forcedWakeUp = false
            return createEvent(map)
        }
}

def sensorValueEvent(value) {
    if (value) {
        createEvent(name: "contact", value: "open", descriptionText: "$device.displayName is open")
    } else {
        createEvent(name: "contact", value: "closed", descriptionText: "$device.displayName is closed")
    }
}

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
    sensorValueEvent(cmd.value)
    if (debugLevel>=2) {log.debug "basicv1.BasicReport $cmd.value"}
}

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
    def theState = cmd.value == 0 ? "closed" : "open"
    if (debugLevel>=2) {log.debug "state.isInitialized : ${state.isInitialized}"}
    if (debugLevel>=2) {log.debug "basicv1.BasicSet $cmd.value"}
    // Use closed/open sensor notification to trigger push of updated Temperature value and immediate setting of updated device parameters
    // Sometimes, Temperature forced refresh stops working : SensorMultilevelGet() Commands are stacked but not executed immediately;
    // will restart after some time, and stacked Commands will be executed !
    def event = createEvent(name:"contact", value:"${theState}", descriptionText:"${device.displayName} is ${theState}", isStateChange:true, displayed:true, linkText:"${device.displayName}")
    def cmdBlock = []
    cmdBlock=wakeUpResponse(cmdBlock)
    return [event, response(cmdBlock)]
}

def zwaveEvent(physicalgraph.zwave.commands.sensorbinaryv2.SensorBinaryReport cmd) {
    if (debugLevel>=2) {log.debug "SensorBinaryReport $cmd"}
       return result
}

def zwaveEvent(physicalgraph.zwave.commands.sensoralarmv1.SensorAlarmReport cmd) {
    //def event = sensorValueEvent(cmd.sensorState)
    if (debugLevel>=2) {log.debug "sensoralarmv1.SensorAlarmReport $cmd.sensorState"}
    def event = createEvent(name:"alarm", descriptionText:"${device.displayName} is tampered with !", isStateChange:true, displayed:true, linkText:"${device.displayName}")
    def cmdBlock = []
    state.forcedWakeUp = true
    cmdBlock=wakeUpResponse(cmdBlock)
    return [event, response(cmdBlock)]
}


def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) { 
    def long nowTime = new Date().time
    if (debugLevel>=2) {
        log.debug "batteryv1.BatteryReport ${cmd.batteryLevel}"
        log.debug "nowTime : ${nowTime}"
        log.debug "state.lastReportBattery : ${state.lastReportBattery}"
        log.debug "state.batteryInterval : ${state.batteryInterval}"
        log.debug "state.forcedWakeUp : ${state.forcedWakeUp}"
    }
    if ((nowTime-state.lastReportBattery > state.batteryInterval) | state.forcedWakeUp) {
        def map = [ name: "battery", displayed: true, isStateChange:true, unit: "%" ]
        if (cmd.batteryLevel == 0xFF) {
            map.value = 1
            map.descriptionText = "${device.displayName} has a low battery"
            map.isStateChange = true
        } else {
            map.value = cmd.batteryLevel
        }
        state.lastReportBattery = nowTime
        log.debug "battery map : ${map}"
        return [createEvent(map)]
    }
}

def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport cmd) {
    if (debugLevel>=2) {log.debug "ConfigurationReport - Parameter#${cmd.parameterNumber}: ${cmd.configurationValue}"}
}

def zwaveEvent(physicalgraph.zwave.commands.multichannelv3.MultiChannelEndPointReport cmd) {
    if (debugLevel>=2) {log.debug "multichannelv3.MultiChannelCapabilityReport: ${cmd}"}
}

def zwaveEvent(physicalgraph.zwave.commands.multichannelv3.MultiChannelCapabilityReport cmd) {
    if (debugLevel>=2) {log.debug "multichannelv3.MultiChannelCapabilityReport: ${cmd}"}
}
 
// MultiChannelCmdEncap and MultiInstanceCmdEncap are ways that devices can indicate that a message
// is coming from one of multiple subdevices or "endpoints" that would otherwise be indistinguishable
def zwaveEvent(physicalgraph.zwave.commands.multichannelv3.MultiChannelCmdEncap cmd) {
        def encapsulatedCommand = cmd.encapsulatedCommand([0x30: 2, 0x31: 2]) // can specify command class versions here like in zwave.parse
        if (debugLevel>=2) {log.debug ("Command from endpoint ${cmd.sourceEndPoint}: ${encapsulatedCommand}")}
        if (encapsulatedCommand) {
                return zwaveEvent(encapsulatedCommand)
        }
}

// Catch All command Handler in case of unexpected message
def zwaveEvent(physicalgraph.zwave.Command cmd) {
    createEvent(descriptionText: "!!! $device.displayName: ${cmd}", displayed: false)
}

///////////////////
// For Tests Purpose
///////////////////

// Executed each time the Handler is updated
def updated() {
    log.debug "Updated !"
    // All state.xxx attributes are Device-local, NOT Location-wide
    state.isInitialized = false
    state.lastReportedTemp = (float) -1000
    state.lastReportTime = (long) 0
    state.lastReportBattery = (long) 0
    // Real-time clock of sensors (ceramic resonator) is up to 3% inaccurate
    state.batteryInterval = (long) (24*60*60-30*60)*1000  // 1 day
    state.parseCount=(int) 0
    state.forcedWakeUp = false
    if (!(state.deviceID)) {state.deviceID = device.name}
    log.debug "state.deviceID: ${state.deviceID}"
    log.debug "state.batteryInterval : ${state.batteryInterval}"
    infos()
}


// If you add the Configuration capability to your device type, this command will be called right
// after the device joins to set device-specific configuration commands.
def configure() {
    log.debug "Configuring..."
    delayBetween([
        // Make sure sleepy battery-powered sensors send their WakeUpNotifications to the hub 
        zwave.wakeUpV1.wakeUpIntervalSet(seconds:60*60, nodeid:zwaveHubNodeId).format(),
        // NOTE : any asynchronous temperature query thru SensorMultilevelGet() does NOT reset the delta-Temp base value (managed by DS18B20 hardware)
        zwave.configurationV2.configurationSet(parameterNumber: 12/*for FGK101*/, size: 1, configurationValue: [5]/* 5/16=0.31°C */).format(),
        // inclusion of Device in Association#3 is needed to get delta-Temperature notification messages [cf Parameter#12 above]
        zwave.associationV2.associationSet(groupingIdentifier:3, nodeId:[zwaveHubNodeId]).format(),
        // inclusion of Device in Association#2 is needed to enable SensorAlarmReport() Command [anti-Tampering protection]
        zwave.associationV2.associationSet(groupingIdentifier:2, nodeId:[zwaveHubNodeId]).format()
    ])
}

def infos() {
    if (!state.devices) { state.devices = [:] }
    log.debug "zwaveHubNodeId: ${zwaveHubNodeId}"                    // -> "1"
    log.debug "device.displayName: ${device.displayName}"            // -> "JJG"
    log.debug "device.id: ${device.id}"                            // -> "d4c9e5b2-ee20-4ffb-8134-8c3e8c73c00a"
    log.debug "device.name: ${device.name}"                        // -> "Z-Wave Door/Window Sensor"
    log.debug "device.label: ${device.label}"                        // -> "JJG"
    log.debug "device.data: ${device.data}"                       // -> "[MSR:010F-0700-2000, endpointId:0]"
    //log.debug "'device.rawDescription': ${device.rawDescription}"    // -> "0 0 0x2001 0 0 0 c 0x30 0x9C 0x60 0x85 0x72 0x70 0x86 0x80 0x84 0x7A 0xEF 0x2B"
}
5 Likes

Oups :frowning:
Further testing showed the delta-Temperature notification does not work properly (but periodic Temperature updates do).
Will update the Handler when it does.

EDIT [4/10/2014] : looks like my testing process was the guilty party and the handler works properly. Sorry for the false alert.

Updated my post to version 0.8 of my custom handler.
It has been working fine for more than 1 month, on 6 different FGK-101 sensors.
All comments welcomed.

Geeji,
Thanks for creating this. I’m just starting to play with SmartThings, possibly migrating from Vera. I currently use some Fibaro Devices including the door/window sensor + DS18b20.

If you wouldn’t mind, how can I use your handler? Do I need to create a developer account and try to publish it to myself?

Also, any tricks to adding the sensor? I’ve tried adding the Fibaro to SmartThings and it doesn’t seem to be recognized at the moment.

Hi Matthew,

First, I assume all your Fibaro Devices are the US Version (908.4 MHz), otherwise they won’t work with the current SmartThings hub (some time in 2015, an international version may become available).
If so, you should be able to join your Fibaro device to your hub following the usual procedure. The Device NEEDS to be recognized by the Hub before you can use it with a custom handler.

Second, you need to create an account at : https://graph.api.smartthings.com/ to access the IDE environment.

And third, when in the IDE, go to “My Device Types / New SmartDevice”, create your own Type and copy/paste the code of my handler (from the first post) into your own Type.
Then Save / Publish For me / Location your_location / Devices your_device

When you look at “My Devices / your_device”, its “Version” should be “self published”.

To check your device is properly using the custom Device Handler, push and release the anti-tampering switch at the bottom of the Fibaro FGK-101 : it should display on your iPhone (or Android equivalent) a tampering alarm and a temperature update.

Note that if you want to display temperatures in Fahrenheits (Fibaro reports °C by default), you need to perform a conversion and modify line 262 of the handler “map.unit = cmd.scale == 1 ? “F” : “C””.

Hope this helps.

Thanks for posting this info here, I’ve been trying to find a temp sensor that is more accurate/reliabel than the others that are available. In looking up the Fibaro FGK-101, I see that the temp sensor isn’t built into the device? How does the DS18B20 connect to the FGK-101? Can you describe or post a picture?

The Fibaro FGK-101 User Manual is there : http://www.fibaro.com/files/instrukcje/eng/DoorWindowSensor%20FGK-101-107%20ENG_v21-v23.pdf.
The DS18B20 sensor is a TO-92 package, that you need to buy as an option for a few $, and which takes about 2 mn to connect inside the FGK-101, following the instructions in the User Manual.
Accuracy is 0.5°C absolute, which means around +/- 0.2°C over the usual temperatures range.

I just received 2 FGK-101 and another 2 are coming.Now I created your device type.The fibaro was recognized then I changed it to your device type.It shows the open/close which works and a blue thermometer.I have attached the temp sensor.(It is a common DS18B20 so I bought them from ebay not from official Fibaro).

The thing is that I do press the bottom of the Fibaro sensor while it is mounted on the door,the blue led blinks but I have no reading on the app.Here is how the sensor is connected.
Why I don’t see a temperature reading in the device?

I also saw in the code the colouring of the temperatures.I also have a Fibaro motion sensor in the same room,which has now a temperature of 19Celsius.Your dark blue says "C <=14 : dark blue "

So I have a reading but it is color-coded?

1 Like

First I confirm that a push on the anti-tampering contact at the bottom of FGK-101 should force an immediate temperature update (unfortunately, the open/close magnet does not do it for some obscure Z-wave reason).

A few things you should check :

  • did you save+publish in your own ST space a copy of my “JJ’s Fibaro FGK-101 Handler” BEFORE attempting the first pairing of your FGK-101 ?
  • just in case, try a different DS18B20 (out of 12 I bought on eBay, 1 was defective); furthermore, I confirm your 3 leads connection is correct
  • make sure your DS18B20 was properly mounted into the FGK-101 and the battery connected BEFORE the FGK-101 was first paired with your ST hub; if you did connect the FGK-101 first WITHOUT a DS18B20, you will have to remove the FGK-101 from the hub Z-wave network, reset it to factory settings (see FGK-101 notice) and then pair it again.

What I find suspect is when you say “The fibaro was recognized then I changed it to your device type” : if you followed the proper procedure above, the ST mobile dashboard should IMMEDIATELY recognize it as “JJ’s Fibaro FGK-101 Handler” type.

If the above is not enough to solve your problem, you have to use the development environment at https://graph.api.smartthings.com/ide/devices, and first check in “My Devices” that “your_FGK-101_physical_device” has the proper attributes :

  • Type *
    “JJ’s Fibaro FGK-101 Handler”

  • Version *
    “Self-Published”

  • Location
    "your_location"

  • Hub
    "your_hub"

  • Group
    "none"

Then go to “My devices Types”, and save+publish your copy of the “JJ’s Fibaro FGK-101 Handler”, Set Location to “your_location” and Install to “your_FGK-101_physical_device”.
Then pressing the anti-tampering switch at the bottom of the FGK-101 should force an immediate temperature update and print at the bottom of the window a long debugging trace.

Hope this helps.
This same driver is currently running at my location with 13 FGK-101 over 12 Hubs and works fine.

The 1st device had this problem but then I installed the 2nd which was found as JJs and worked.Then the 1st one worked also (or I unistalled it and installed again,can’t remember).But I have no problem now,thank you!

I found this thread when I was looking for temperature support for FGK-101. Although the official SmartThings device type doesn’t seem to support temperature readings, it has all of the necessary code to do so. Just create a new device type from their template, and search the code for “NO TEMP”. You’ll need to uncomment two lines, comment two others, and uncomment the “Temperature Measurement” capability. That’s it! This worked much better for my US Fibaro than JJ’s version.

I am just curious to know what did not work for you with my FGK-101 custom driver.
Mine has been working fine for more than a year for a dozen FGK-101 US.
Which does not say that I have not suffered plenty of problems due to the catastrophic instability of the SmartThings cloud
 :frowning:

Careful reading of the instructions reveals that there is a ten-minute delay after connection, before the temperature will display anything but the error code “-99”.
I removed and re-installed my DS18B20 three times before I gave up, then came back a bit later and discovered that the temperature was displayed in the app.

hi, I have tied to change the code three times but I always get a blank white screen when i go to ‘right now’ on the sensor. i have also tried 2 different sensors! any ideals?

When I checked the ‘recently’ it shows the temp change.

code:

/**

  • Device Type Definition File
  • Device Type: Fibaro Door/Window Sensor
  • File Name: fibaro-door-window-sensor.groovy
  • Initial Release: 2014-12-10
  • @author: Todd Wackford
  • Email: todd@wackford.net
  • @version: 1.0
  • Copyright 2014 SmartThings
  • 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.

*/

/**

  • Sets up metadata, simulator info and tile definition. The tamper tile is setup, but

  • not displayed to the user. We do this so we can receive events and display on device

  • activity. If the user wants to display the tamper tile, adjust the tile display lines

  • with the following:

  •  main(["contact", "temperature", "tamper"])
    
  •  details(["contact", "temperature", "battery", "tamper"])
    
  • @param none

  • @return none
    */
    metadata {
    definition (name: “Fibaro Door/Window Sensor t”, namespace: “smartthings”, author: “SmartThings”) {
    capability “Temperature Measurement” //UNCOMMENT ME IF TEMP INSTALLED
    capability "Contact Sensor"
    capability "Sensor"
    capability "Battery"
    capability “Configuration”

     command		"resetParams2StDefaults"
     command		"listCurrentParams"
     command		"updateZwaveParam"
     command		"test"
    
     fingerprint deviceId: "0x2001", inClusters: "0x30,0x9C,0x85,0x72,0x70,0x86,0x80,0x56,0x84,0x7A,0xEF,0x2B"
    

    }

    simulator {
    // messages the device returns in response to commands it receives
    status “open” : "command: 2001, payload: FF"
    status “closed”: “command: 2001, payload: 00”

     for (int i = 0; i <= 100; i += 20) {
     	status "temperature ${i}F": new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
     		scaledSensorValue: i, precision: 1, sensorType: 1, scale: 1).incomingMessage()
     }
    
     for (int i = 0; i <= 100; i += 20) {
     	status "battery ${i}%": new physicalgraph.zwave.Zwave().batteryV1.batteryReport(
     		batteryLevel: i).incomingMessage()
     }
    

    }

    tiles {
    standardTile(“contact”, “device.contact”, 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”
    }
    valueTile(“temperature”, “device.temperature”, inactiveLabel: false) {
    state “temperature”, label:’${currentValue}°’,
    backgroundColors:[
    [value: “”, color: “#ffffff”],
    [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(“tamper”, “device.alarm”) {
    state(“secure”, label:‘secure’, icon:“st.locks.lock.locked”, backgroundColor:”#ffffff")
    state(“tampered”, label:‘tampered’, icon:“st.locks.lock.unlocked”, backgroundColor:"#53a7c0")
    }
    valueTile(“battery”, “device.battery”, inactiveLabel: false, decoration: “flat”) {
    state “battery”, label:’${currentValue}% battery’, unit:""
    }
    standardTile(“configure”, “device.configure”, inactiveLabel: false, decoration: “flat”) {
    state “configure”, label:’’, action:“configuration.configure”, icon:“st.secondary.configure”
    }

     //this will display a temperature tile for the DS18B20 sensor
     main(["contact", "temperature"])						//COMMENT ME OUT IF NO TEMP INSTALLED
     details(["contact", "temperature", "battery"])			//COMMENT ME OUT IF NO TEMP INSTALLED
     
     //this will hide the temperature tile if the DS18B20 sensor is not installed
     //main(["contact"])										//UNCOMMENT ME IF NO TEMP INSTALLED
     //details(["contact", "battery"])						//UNCOMMENT ME IF NO TEMP INSTALLED
    

    }
    }

// Parse incoming device messages to generate events
def parse(String description)
{
def result = []
def cmd = zwave.parse(description, [0x30: 1, 0x84: 1, 0x9C: 1, 0x70: 2, 0x80: 1, 0x72: 2, 0x56: 1, 0x60: 3])
if (cmd) {
result += zwaveEvent(cmd)
}
log.debug "parsed ‘$description’ to ${result.inspect()}"
result
}

def zwaveEvent(physicalgraph.zwave.commands.crc16encapv1.Crc16Encap cmd)
{
def versions = [0x30: 1, 0x84: 1, 0x9C: 1, 0x70: 2, 0x80: 1, 0x72: 2, 0x60: 3]
// def encapsulatedCommand = cmd.encapsulatedCommand(versions)
def version = versions[cmd.commandClass as Integer]
def ccObj = version ? zwave.commandClass(cmd.commandClass, version) : zwave.commandClass(cmd.commandClass)
def encapsulatedCommand = ccObj?.command(cmd.command)?.parse(cmd.data)
if (!encapsulatedCommand) {
log.debug “Could not extract command from $cmd”
} else {
return zwaveEvent(encapsulatedCommand)
}
}

def zwaveEvent(physicalgraph.zwave.commands.multichannelv3.MultiChannelCmdEncap cmd) {
def encapsulatedCommand = cmd.encapsulatedCommand([0x30: 2, 0x31: 2]) // 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.commands.wakeupv1.WakeUpNotification cmd)
{
def event = createEvent(descriptionText: “${device.displayName} woke up”, isStateChange: false)
def cmds = []
if (!state.lastbat || now() - state.lastbat > 246060*1000) {
cmds << zwave.batteryV1.batteryGet().format()
} else {
cmds << zwave.wakeUpV1.wakeUpNoMoreInformation().format()
}
[event, response(cmds)]
}

def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv2.SensorMultilevelReport cmd)
{
def map = [:]
switch (cmd.sensorType) {
case 1:
// temperature
def cmdScale = cmd.scale == 1 ? “F” : "C"
map.value = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmdScale, cmd.precision)
map.unit = getTemperatureScale()
map.name = "temperature"
break;
}
createEvent(map)
}

def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
def map = [ name: “battery”, unit: “%” ]
if (cmd.batteryLevel == 0xFF) {
map.value = 1
map.descriptionText = "${device.displayName} has a low battery"
map.isStateChange = true
} else {
map.value = cmd.batteryLevel
}
state.lastbat = now()
[createEvent(map), response(zwave.wakeUpV1.wakeUpNoMoreInformation())]
}

def zwaveEvent(physicalgraph.zwave.commands.sensorbinaryv1.SensorBinaryReport cmd) {
def map = [:]
map.value = cmd.sensorValue ? “open” : "closed"
map.name = "contact"
if (map.value == “closed”) {
map.descriptionText = “$device.displayName is closed”
}
else {
map.descriptionText = “$device.displayName is open”
}
createEvent(map)
}

// added so UK (non-multichannel) and US device supported by same device file.
def sensorValueEvent(value) {
if (value) {
createEvent(name: “contact”, value: “open”, descriptionText: “$device.displayName is open”)
} else {
createEvent(name: “contact”, value: “closed”, descriptionText: “$device.displayName is closed”)
}
}

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd)
{
sensorValueEvent(cmd.value)
}

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd)
{
sensorValueEvent(cmd.value)
}

def zwaveEvent(physicalgraph.zwave.commands.sensoralarmv1.SensorAlarmReport cmd)
{
def map = [:]
map.value = cmd.sensorState ? “tampered” : "secure"
map.name = "tamper"
if (map.value == “tampered”) {
map.descriptionText = “$device.displayName has been tampered with”
}
else {
map.descriptionText = “$device.displayName is secure”
}
createEvent(map)
}

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

def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport cmd) {
def result = []
log.debug “${device.displayName} parameter ‘${cmd.parameterNumber}’ with a byte size of ‘${cmd.size}’ is set to ‘${cmd.configurationValue}’”

if (cmd.parameterNumber == 15) {
	if (cmd.configurationValue[0] == 1) { //error in temp probe
		result << createEvent(name:"temperature", value:"-99")
	} else if (cmd.configurationValue[0] == 255) { //no temp probe
		result << createEvent(name:"temperature", value:"")
	}
	result += response(zwave.batteryV1.batteryGet().format())  // send this after configure() runs
}
result

}

def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
def result = []

def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
log.debug "msr: $msr"
device.updateDataValue(["MSR", msr])

result << createEvent(descriptionText: "$device.displayName MSR: $msr", isStateChange: false)
result

}

/**

  • Configures the device to settings needed by SmarthThings at device discovery time.

  • @param none

  • @return none
    */
    def configure() {
    log.debug "Configuring Device
"
    def cmds = []
    cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 1, size: 2).format()
    // send associate to group 3 to get sensor data reported only to hub
    cmds << zwave.associationV2.associationSet(groupingIdentifier:3, nodeId:[zwaveHubNodeId]).format()

    // send associate to group 2 to get tamper alarm data reported
    cmds << zwave.associationV2.associationSet(groupingIdentifier:2, nodeId:[zwaveHubNodeId]).format()

    // turn on the tamper alarm
    cmds << zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 10, size: 1).format()
    //cmds << zwave.configurationV1.configurationGet(parameterNumber: 10).format()

    // temperature change sensitivity
    cmds << zwave.configurationV1.configurationSet(configurationValue: [4], parameterNumber: 12, size: 1).format()
    //cmds << zwave.configurationV1.configurationGet(parameterNumber: 12).format()

    // remove group 1 association to stop redundant BasicSet
    cmds << zwave.associationV1.associationRemove(groupingIdentifier:1, nodeId:zwaveHubNodeId).format()

    // see if there is a temp probe on board and is it working
    cmds << zwave.configurationV1.configurationGet(parameterNumber: 15).format()

    delayBetween(cmds, 500)
    }

//used to add “test” button for simulation of user changes to parameters
def test() {
def params = [paramNumber:10,value:1,size:1]
updateZwaveParam(params)
//zwave.wakeUpV1.wakeUpIntervalSet(seconds: 30, nodeid:zwaveHubNodeId).format()
}

/**

  • This method will allow the user to update device parameters (behavior) from an app.

  • A “Zwave Tweaker” app will be developed as an interface to do this. Or the user can

  • write his/her own app to envoke this method. No type or value checking is done to

  • compare to what device capability or reaction. It is up to user to read OEM

  • documentation prio to envoking this method.

  • THIS IS AN ADVANCED OPERATION. USE AT YOUR OWN RISK! READ OEM DOCUMENTATION!

  • @param List[paramNumber:80,value:10,size:1]

  • @return none
    */
    def updateZwaveParam(params) {
    if ( params ) {
    def pNumber = params.paramNumber
    def pSize = params.size
    def pValue = [params.value]
    log.debug "Make sure device is awake and in recieve mode"
    log.debug “Updating ${device.displayName} parameter number ‘${pNumber}’ with value ‘${pValue}’ with size of ‘${pSize}’”

     def cmds = []
     cmds << zwave.configurationV1.configurationSet(configurationValue: pValue, parameterNumber: pNumber, size: pSize).format()
     cmds << zwave.configurationV1.configurationGet(parameterNumber: pNumber).format()
     delayBetween(cmds, 1000)        
    

    }
    }

/**

  • Sets all of available Fibaro parameters back to the device defaults except for what

  • SmartThings needs to support the stock functionality as released. This will be

  • called from the “Fibaro Tweaker” or user’s app.

  • THIS IS AN ADVANCED OPERATION. USE AT YOUR OWN RISK! READ OEM DOCUMENTATION!

  • @param none

  • @return none
    */
    def resetParams2StDefaults() {
    log.debug "Resetting ${device.displayName} parameters to SmartThings compatible defaults"
    def cmds = []
    cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 1, size: 2).format()
    cmds << zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 2, size: 1).format()
    cmds << zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 3, size: 1).format()
    cmds << zwave.configurationV1.configurationSet(configurationValue: [255], parameterNumber: 5, size: 1).format()
    cmds << zwave.configurationV1.configurationSet(configurationValue: [255], parameterNumber: 7, size: 1).format()
    cmds << zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 9, size: 1).format()
    cmds << zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 10, size: 1).format() //ST Custom
    cmds << zwave.configurationV1.configurationSet(configurationValue: [4], parameterNumber: 12, size: 1).format() //St Custom
    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)
    }

/**

  • Lists all of available Fibaro parameters and thier current settings out to the

  • logging window in the IDE. This will be called from the “Fibaro Tweaker” or

  • user’s own app.

  • THIS IS AN ADVANCED OPERATION. USE AT YOUR OWN RISK! READ OEM DOCUMENTATION!

  • @param none

  • @return none
    */
    def listCurrentParams() {
    log.debug "Listing of current parameter settings of ${device.displayName}"
    def cmds = []
    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: 5).format()
    cmds << zwave.configurationV1.configurationGet(parameterNumber: 7).format()
    cmds << zwave.configurationV1.configurationGet(parameterNumber: 9).format()
    cmds << zwave.configurationV1.configurationGet(parameterNumber: 10).format()
    cmds << zwave.configurationV1.configurationGet(parameterNumber: 12).format()
    cmds << zwave.configurationV1.configurationGet(parameterNumber: 13).format()
    cmds << zwave.configurationV1.configurationGet(parameterNumber: 14).format()
    cmds << zwave.configurationV1.configurationGet(parameterNumber: 15).format()

    delayBetween(cmds, 500)
    }

Any chance someone could help provide updated step by step instructions for this or for editing the actual Fibaro code? I believe I’ve followed the instructions above, but can’t seem to get this to work at all. Not only the temperature, but even the open/close status isn’t updated in SmartThings when using this code (the open/close works fine with the default device, but then no temperature
).

I’ve copied and pasted the code, published, edited the device and selected the handler, selected self-published, but no status updates at all change in the custom device.

Please help!

Difficult to understand your problem with so little information : obviously, your Device is properly paired with your Hub, and it uses the proper custom handler.
A few suggestions to try :

  • check the proper electrical connection of the optional DS18B20 sensor into the FGK-101
  • the DS18B20 must be installed BEFORE pairing the FGK-101 to the Hub; if it was installed AFTER, you need to unpair the FGK-101 from your Hub, RESET it (according to the instructions within the FGK-101 Datasheet) and then re-PAIR the FGK-101 to your Hub
  • use “List Events ALL” to check the FGK-101 Device activity; at the minimum, you should see a device wake-up every hour

This same driver has been working fine for me with 11 FGK-101 for more than 1 year.
Note that the open/close status update is done ONLY when there is some actual open/close activity : use the magnet to check it works.

Hope this helps.

I’ve checked off your suggestions, and the open/close status still isn’t updating on my end, but that isn’t my main concern (I can use the original device handler for that
) - I just want the temperature information! :slight_smile:

I ordered two DS18B20’s off Amazon and both were faulty. I ordered a pack of 5 off eBay for the same price and struck gold with the first one. I’m finally getting a reading instead of just -99° like I had with the two faulty DS18B20s originally.

Now that my temperarture information is working, do you mind elaborating a bit on changing to Fahrenheit readings? I am a total code rookie. Any insight would be appreciated!

Note that if you want to display temperatures in Fahrenheits (Fibaro
reports °C by default), you need to perform a conversion and modify line
262 of the handler “map.unit = cmd.scale == 1 ? “F” : “C””.

Edit: Maybe I lied as now I’m getting a reading of 73.2. However, it doesn’t seem to update, even though I’ve pushed the button on the sensor and waited over an hour! What gives? Why is none of this updating?

First I apologize for the faulty mention of a °C to °F conversion : the way the Device Handler is coded, the conversion is performed automatically based on the °F/°C selection you did for your own location.

Regarding the temperature update, whenever you have a (5/16 = ) 0,3125°C / 0,562 °F temperature difference, you should get a temperature event reported to the hub.
Even when the temperature remains stable with less than 0,3125°C fluctuations, you should get a temperature event every 4 hours.

Based on the “Current States” of your picture, there is however something fishy in your copy of the “JJ’s Fibaro FGK-101 Handler” ; it lists only Current States = {temperature:, battery:}, when it should list {temperature:, battery:, contact:, alarm:, reportASAP:}.
It is probably related to the way you created your own copy of “JJ’s Fibaro FGK-101 Handler” : if you check in the IDE My Device Handlers / Capabilities[right column], you should see {Alarm, Battery, Configuration, Contact Sensor, Sensor, Temperature Measurement}.
If you don’t, you need to recreate your copy of “JJ’s Fibaro FGK-101 Handler”, this time with the right capabilities.

To do that :

  1. [ST mobile App] : unpair your Fibaro FGK-101 Device from your hub
  2. [FGK-101] : reset your Fibaro FGK-101 Device (following the instructions within the FGK-101 Datasheet)
  3. [IDE] : delete your current version of Device Handler “JJ’s Fibaro FGK-101 Handler” (IDE / My Device Handlers / Edit / Delete)
  4. [IDE] : create a new Device Handler +++From Code+++, copying the whole code of “JJ’s Fibaro FGK-101 Handler” as given in Post #1 of this thread
  5. [IDE] : verify this new Device Handler is “published for you” in your own name space;
    verify you now have listed the right Capabilities: {Alarm, Battery, Configuration, Contact Sensor, Sensor, Temperature Measurement}
  6. [ST mobile App] : pair again your Fibaro FGK-101 Device with your hub; click the “tamper switch” at the bottom to force immediate States updates

Those 6 steps may not be all mandatory, depending on the exact source of your problems, but making all of them will guarantee a cleaner state at the end.

Let me know if it works :slight_smile:

Thanks for this Geeji.

While the device is reporting temperature in the logs, I don’t see a temperature tile and it’s not showing up as a temp sensor for rules/apps. Any ideas?

edit: this is using code from the 1st post as of today, April 14th 2016.


@johnny2678 : unless you modified several messages in my “JJ’s Fibaro FGK-101 Handler”, I very much doubt your FGK-101 is using my custom Device Handler : the messages you show in your Log are NOT as specified in my own handler, since they should be :

AV Temp Sensor
Temperature Is xxxx°F

AV Temp Sensor
Is Tampered With !

while this one does not exist within my custom handler :

AV Temp Sensor
AV Temp Sensor is secure

To check what version of handler you are using, go into the IDE / My Devices / AV Temp Sensor ; then check it shows :

Type	        JJ's Fibaro FGK-101 Handler
Version	Self-Published

I am sorry you have so many exotic problems with something which was initially supposed to be mostly “cut & paste”; but I discovered (painfully) that almost nothing in SmartThings is as simple as it looks initially
 :frowning: