diff --git a/build.gradle b/build.gradle index 2667f45..8f7b27b 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ apply plugin: 'smartthings-slack' buildscript { dependencies { - classpath "com.smartthings.deployment:executable-deployment-scripts:1.0.8" + classpath "com.smartthings.deployment:executable-deployment-scripts:1.0.11" } repositories { mavenLocal() diff --git a/devicetypes/fibargroup/fibaro-flood-sensor-zw5.src/fibaro-flood-sensor-zw5.groovy b/devicetypes/fibargroup/fibaro-flood-sensor-zw5.src/fibaro-flood-sensor-zw5.groovy index bf691d8..4d7f872 100644 --- a/devicetypes/fibargroup/fibaro-flood-sensor-zw5.src/fibaro-flood-sensor-zw5.groovy +++ b/devicetypes/fibargroup/fibaro-flood-sensor-zw5.src/fibaro-flood-sensor-zw5.groovy @@ -21,6 +21,7 @@ metadata { capability "Tamper Alert" capability "Temperature Measurement" capability "Water Sensor" + capability "Health Check" fingerprint deviceId: "0x0701", inClusters: "0x5E, 0x22, 0x85, 0x59, 0x20, 0x80, 0x70, 0x56, 0x5A, 0x7A, 0x72, 0x8E, 0x71, 0x73, 0x98, 0x9C, 0x31, 0x86", outClusters: "" } @@ -228,7 +229,9 @@ def zwaveEvent(physicalgraph.zwave.commands.deviceresetlocallyv1.DeviceResetLoca def configure() { log.debug "Executing 'configure'" - + // Device-Watch simply pings if no device events received for 8 hrs & 2 minutes + sendEvent(name: "checkInterval", value: 8 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) + def cmds = [] cmds += zwave.wakeUpV2.wakeUpIntervalSet(seconds:21600, nodeid: zwaveHubNodeId)//FGFS' default wake up interval diff --git a/devicetypes/fibargroup/fibaro-motion-sensor-zw5.src/fibaro-motion-sensor-zw5.groovy b/devicetypes/fibargroup/fibaro-motion-sensor-zw5.src/fibaro-motion-sensor-zw5.groovy index b3be160..ca47295 100644 --- a/devicetypes/fibargroup/fibaro-motion-sensor-zw5.src/fibaro-motion-sensor-zw5.groovy +++ b/devicetypes/fibargroup/fibaro-motion-sensor-zw5.src/fibaro-motion-sensor-zw5.groovy @@ -22,6 +22,7 @@ metadata { capability "Sensor" capability "Tamper Alert" capability "Temperature Measurement" + capability "Health Check" fingerprint deviceId: "0x0701", inClusters: "0x5E, 0x20, 0x86, 0x72, 0x5A, 0x59, 0x85, 0x73, 0x84, 0x80, 0x71, 0x56, 0x70, 0x31, 0x8E, 0x22, 0x30, 0x9C, 0x98, 0x7A", outClusters: "" } @@ -240,7 +241,9 @@ def zwaveEvent(physicalgraph.zwave.commands.deviceresetlocallyv1.DeviceResetLoca def configure() { log.debug "Executing 'configure'" - + // Device-Watch simply pings if no device events received for 8 hrs & 2 minutes + sendEvent(name: "checkInterval", value: 8 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) + def cmds = [] cmds += zwave.wakeUpV2.wakeUpIntervalSet(seconds: 7200, nodeid: zwaveHubNodeId)//FGMS' default wake up interval diff --git a/devicetypes/smartthings/fibaro-flood-sensor.src/fibaro-flood-sensor.groovy b/devicetypes/smartthings/fibaro-flood-sensor.src/fibaro-flood-sensor.groovy index 7759d85..ed01e44 100644 --- a/devicetypes/smartthings/fibaro-flood-sensor.src/fibaro-flood-sensor.groovy +++ b/devicetypes/smartthings/fibaro-flood-sensor.src/fibaro-flood-sensor.groovy @@ -39,6 +39,7 @@ metadata { capability "Temperature Measurement" capability "Configuration" capability "Battery" + capability "Health Check" command "resetParams2StDefaults" command "listCurrentParams" @@ -304,6 +305,9 @@ def lateConfigure(setConf = False) { */ def configure() { log.debug "Configuring Device..." + // Device-Watch simply pings if no device events received for 8 hrs & 2 minutes + sendEvent(name: "checkInterval", value: 8 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) + def cmds = [] // send associate to group 2 to get alarm data diff --git a/devicetypes/smartthings/fibaro-motion-sensor.src/fibaro-motion-sensor.groovy b/devicetypes/smartthings/fibaro-motion-sensor.src/fibaro-motion-sensor.groovy index 96258c3..891907a 100644 --- a/devicetypes/smartthings/fibaro-motion-sensor.src/fibaro-motion-sensor.groovy +++ b/devicetypes/smartthings/fibaro-motion-sensor.src/fibaro-motion-sensor.groovy @@ -46,6 +46,7 @@ capability "Illuminance Measurement" capability "Sensor" capability "Battery" + capability "Health Check" command "resetParams2StDefaults" command "listCurrentParams" @@ -125,6 +126,9 @@ */ def configure() { log.debug "Configuring Device For SmartThings Use" + // Device-Watch simply pings if no device events received for 8 hrs & 2 minutes + sendEvent(name: "checkInterval", value: 8 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) + def cmds = [] // send associate to group 3 to get sensor data reported only to hub diff --git a/smartapps/opent2t/opent2t-smartapp-test.src/opent2t-smartapp-test.groovy b/smartapps/opent2t/opent2t-smartapp-test.src/opent2t-smartapp-test.groovy index 9951cfa..91ddaef 100644 --- a/smartapps/opent2t/opent2t-smartapp-test.src/opent2t-smartapp-test.groovy +++ b/smartapps/opent2t/opent2t-smartapp-test.src/opent2t-smartapp-test.groovy @@ -39,7 +39,7 @@ definition( * garageDoors | door | open, close | unknown, closed, open, closing, opening * cameras | image | take | * thermostats | thermostat | setHeatingSetpoint, | temperature, heatingSetpoint, coolingSetpoint, - * | | setCoolingSetpoint, | thermostatSetpoint, thermostatMode, + * | | setCoolingSetpoint, | thermostatSetpoint, thermostatMode, * | | off, heat, cool, auto,| thermostatFanMode, thermostatOperatingState * | | emergencyHeat, | * | | setThermostatMode, | @@ -55,7 +55,7 @@ preferences { input "contactSensors", "capability.contactSensor", title: "Which Contact Sensors", multiple: true, required: false input "garageDoors", "capability.garageDoorControl", title: "Which Garage Doors?", multiple: true, required: false input "locks", "capability.lock", title: "Which Locks?", multiple: true, required: false - input "cameras", "capability.videoCapture", title: "Which Cameras?", multiple: true, required: false + input "cameras", "capability.videoCapture", title: "Which Cameras?", multiple: true, required: false input "motionSensors", "capability.motionSensor", title: "Which Motion Sensors?", multiple: true, required: false input "presenceSensors", "capability.presenceSensor", title: "Which Presence Sensors", multiple: true, required: false input "switches", "capability.switch", title: "Which Switches and Lights?", multiple: true, required: false @@ -66,54 +66,48 @@ preferences { def getInputs() { def inputList = [] - inputList += contactSensors ?: [] - inputList += garageDoors ?: [] - inputList += locks ?: [] - inputList += cameras ?: [] - inputList += motionSensors ?: [] - inputList += presenceSensors ?: [] - inputList += switches ?: [] - inputList += thermostats ?: [] - inputList += waterSensors ?: [] + inputList += contactSensors?: [] + inputList += garageDoors?: [] + inputList += locks?: [] + inputList += cameras?: [] + inputList += motionSensors?: [] + inputList += presenceSensors?: [] + inputList += switches?: [] + inputList += thermostats?: [] + inputList += waterSensors?: [] return inputList } //API external Endpoints mappings { path("/subscriptionURL/:url") { - action: - [ + action: [ PUT: "updateEndpointURL" ] } path("/connectionId/:connId") { - action: - [ + action: [ PUT: "updateConnectionId" ] } path("/devices") { - action: - [ + action: [ GET: "getDevices" ] } path("/devices/:id") { - action: - [ + action: [ GET: "getDevice" ] } path("/update/:id") { - action: - [ + action: [ PUT: "updateDevice" ] } path("/subscription/:id") { - action: - [ - POST : "registerDeviceChange", + action: [ + POST: "registerDeviceChange", DELETE: "unregisterDeviceChange" ] } @@ -145,7 +139,7 @@ def registerSubscriptions() { def registerChangeHandler(myList) { myList.each { myDevice -> def theAtts = myDevice.supportedAttributes - theAtts.each { att -> + theAtts.each {att -> subscribe(myDevice, att.name, eventHandler) log.info "Registering ${myDevice.displayName}.${att.name}" } @@ -157,7 +151,7 @@ def registerDeviceChange() { def myDevice = findDevice(params.id) def theAtts = myDevice.supportedAttributes try { - theAtts.each { att -> + theAtts.each {att -> subscribe(myDevice, att.name, eventHandler) log.info "Registering ${myDevice.displayName}.${att.name}" } @@ -186,16 +180,20 @@ def eventHandler(evt) { def evt_name = evt.name def evt_device = evt.device def evt_deviceType = getDeviceType(evt_device); + def deviceInfo + + if(evt_deviceType == "thermostat") + { + deviceInfo = [name: evt_device.displayName, id: evt_device.id, status:evt_device.getStatus(), deviceType:evt_deviceType, manufacturer:evt_device.getManufacturerName(), model:evt_device.getModelName(), attributes: deviceAttributeList(evt_device), locationMode: getLocationModeInfo()] + } + else + { + deviceInfo = [name: evt_device.displayName, id: evt_device.id, status:evt_device.getStatus(), deviceType:evt_deviceType, manufacturer:evt_device.getManufacturerName(), model:evt_device.getModelName(), attributes: deviceAttributeList(evt_device)] + } + def params = [ - uri : "${state.endpointURL}/${state.connectionId}", - body: [ - name : evt_device.displayName, - id : evt_device.id, - deviceType : evt_deviceType, - manufacturer: evt_device.getManufacturerName(), - model : evt_device.getModelName(), - attributes : deviceAttributeList(evt_device) - ] + uri: "${state.endpointURL}/${state.connectionId}", + body: [ deviceInfo ] ] try { log.trace "POST URI: ${params.uri}" @@ -230,10 +228,13 @@ def getDevices() { def deviceData = [] inputs?.each { def deviceType = getDeviceType(it) - if (deviceType == "thermostat") { - deviceData << [name: it.displayName, id: it.id, deviceType: deviceType, manufacturer: it.getManufacturerName(), model: it.getModelName(), attributes: deviceAttributeList(it), locationMode: getLocationModeInfo()] - } else { - deviceData << [name: it.displayName, id: it.id, deviceType: deviceType, manufacturer: it.getManufacturerName(), model: it.getModelName(), attributes: deviceAttributeList(it)] + if(deviceType == "thermostat") + { + deviceData << [name: it.displayName, id: it.id, status:it.getStatus(), deviceType:deviceType, manufacturer:it.getManufacturerName(), model:it.getModelName(), attributes: deviceAttributeList(it), locationMode: getLocationModeInfo()] + } + else + { + deviceData << [name: it.displayName, id: it.id, status:it.getStatus(), deviceType:deviceType, manufacturer:it.getManufacturerName(), model:it.getModelName(), attributes: deviceAttributeList(it)] } } @@ -246,10 +247,13 @@ def getDevice() { def it = findDevice(params.id) def deviceType = getDeviceType(it) def device - if (deviceType == "thermostat") { - device = [name: it.displayName, id: it.id, deviceType: deviceType, manufacturer: it.getManufacturerName(), model: it.getModelName(), attributes: deviceAttributeList(it), locationMode: getLocationModeInfo()] - } else { - device = [name: it.displayName, id: it.id, deviceType: deviceType, manufacturer: it.getManufacturerName(), model: it.getModelName(), attributes: deviceAttributeList(it)] + if(deviceType == "thermostat") + { + device = [name: it.displayName, id: it.id, status:it.getStatus(), deviceType:deviceType, manufacturer:it.getManufacturerName(), model:it.getModelName(), attributes: deviceAttributeList(it), locationMode: getLocationModeInfo()] + } + else + { + device = [name: it.displayName, id: it.id, status:it.getStatus(), deviceType:deviceType, manufacturer:it.getManufacturerName(), model:it.getModelName(), attributes: deviceAttributeList(it)] } log.debug "getDevice, return: ${device}" return device @@ -261,18 +265,18 @@ void updateDevice() { request.JSON.each { def command = it.key def value = it.value - if (command) { + if (command){ def commandList = mapDeviceCommands(command, value) command = commandList[0] value = commandList[1] if (command == "setAwayMode") { log.info "Setting away mode to ${value}" - if (location.modes?.find { it.name == value }) { + if (location.modes?.find {it.name == value}) { location.setMode(value) } - } else if (command == "thermostatSetpoint") { - switch (device.currentThermostatMode) { + }else if (command == "thermostatSetpoint"){ + switch(device.currentThermostatMode){ case "cool": log.info "Update: ${device.displayName}, [${command}, ${value}]" device.setCoolingSetpoint(value) @@ -286,7 +290,7 @@ void updateDevice() { httpError(501, "this mode: ${device.currentThermostatMode} does not allow changing thermostat setpoint.") break } - } else if (!device) { + }else if (!device) { log.error "updateDevice, Device not found" httpError(404, "Device not found") } else if (!device.hasCommand(command)) { @@ -296,11 +300,11 @@ void updateDevice() { if (command == "setColor") { log.info "Update: ${device.displayName}, [${command}, ${value}]" device."$command"(hex: value) - } else if (value.isNumber()) { + } else if(value.isNumber()) { def intValue = value as Integer log.info "Update: ${device.displayName}, [${command}, ${intValue}(int)]" device."$command"(intValue) - } else if (value) { + } else if (value){ log.info "Update: ${device.displayName}, [${command}, ${value}]" device."$command"(value) } else { @@ -322,19 +326,28 @@ private getLocationModeInfo() { //Map each device to a type given it's capabilities private getDeviceType(device) { def deviceType - def caps = device.capabilities - log.debug "capabilities: [${device}, ${caps}]" + def capabilities = device.capabilities + log.debug "capabilities: [${device}, ${capabilities}]" log.debug "supported commands: [${device}, ${device.supportedCommands}]" - caps.each { - switch (it.name.toLowerCase()) { + + //Loop through the device capability list to determine the device type. + capabilities.each {capability -> + switch(capability.name.toLowerCase()) + { case "switch": deviceType = "switch" - if (caps.any { it.name.toLowerCase() == "power meter" }) { - return deviceType - } - if (caps.any { it.name.toLowerCase() == "switch level" }) { - deviceType = "light" - return deviceType + + //If the device also contains "Switch Level" capability, identify it as a "light" device. + if (capabilities.any{it.name.toLowerCase() == "switch level"}){ + + //If the device also contains "Power Meter" capability, identify it as a "dimmerSwitch" device. + if (capabilities.any{it.name.toLowerCase() == "power meter"}){ + deviceType = "dimmerSwitch" + return deviceType + } else { + deviceType = "light" + return deviceType + } } break case "contact sensor": @@ -375,16 +388,16 @@ private findDevice(deviceId) { //Return a list of device attributes private deviceAttributeList(device) { - device.supportedAttributes.collectEntries { attribute -> + device.supportedAttributes.collectEntries { attribute-> try { - [(attribute.name): device.currentValue(attribute.name)] - } catch (e) { - [(attribute.name): null] + [ (attribute.name): device.currentValue(attribute.name) ] + } catch(e) { + [ (attribute.name): null ] } } } -//Map device command and value. +//Map device command and value. //input command and value are from UWP, //returns resultCommand and resultValue that corresponds with function and value in SmartApps private mapDeviceCommands(command, value) { @@ -414,7 +427,7 @@ private mapDeviceCommands(command, value) { resultCommand = "setSaturation" resultValue = value break - case "ct": + case "colorTemperature": resultCommand = "setColorTemperature" resultValue = value break @@ -451,7 +464,8 @@ private mapDeviceCommands(command, value) { if (value == 1 || value == "1" || value == "lock") { resultCommand = "lock" resultValue = "" - } else if (value == 0 || value == "0" || value == "unlock") { + } + else if (value == 0 || value == "0" || value == "unlock") { resultCommand = "unlock" resultValue = "" } @@ -460,6 +474,5 @@ private mapDeviceCommands(command, value) { break } - return [resultCommand, resultValue] + return [resultCommand,resultValue] } -