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/capabilities/acceleration-sensor-capability.src/acceleration-sensor-capability.groovy b/devicetypes/capabilities/acceleration-sensor-capability.src/acceleration-sensor-capability.groovy index 14ec809..a1e00b7 100644 --- a/devicetypes/capabilities/acceleration-sensor-capability.src/acceleration-sensor-capability.groovy +++ b/devicetypes/capabilities/acceleration-sensor-capability.src/acceleration-sensor-capability.groovy @@ -23,8 +23,8 @@ metadata { tiles { standardTile("acceleration", "device.acceleration", width: 2, height: 2) { - state("inactive", label:'${name}', icon:"st.motion.acceleration.inactive", backgroundColor:"#ffffff") - state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#53a7c0") + state("inactive", label:'${name}', icon:"st.motion.acceleration.inactive", backgroundColor:"#cccccc") + state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#00A0DC") } main "acceleration" diff --git a/devicetypes/capabilities/contact-sensor-capability.src/contact-sensor-capability.groovy b/devicetypes/capabilities/contact-sensor-capability.src/contact-sensor-capability.groovy index 1aa6f22..a134693 100644 --- a/devicetypes/capabilities/contact-sensor-capability.src/contact-sensor-capability.groovy +++ b/devicetypes/capabilities/contact-sensor-capability.src/contact-sensor-capability.groovy @@ -23,8 +23,8 @@ metadata { tiles { standardTile("contact", "device.contact", width: 2, height: 2) { - state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821") - state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e") + state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#00A0DC") + state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#e86d13") } main "contact" details "contact" diff --git a/devicetypes/capabilities/lock-capability.src/lock-capability.groovy b/devicetypes/capabilities/lock-capability.src/lock-capability.groovy index 634e7c6..dde6b62 100644 --- a/devicetypes/capabilities/lock-capability.src/lock-capability.groovy +++ b/devicetypes/capabilities/lock-capability.src/lock-capability.groovy @@ -27,7 +27,7 @@ metadata { tiles { standardTile("toggle", "device.lock", width: 2, height: 2) { state "unlocked", label:'unlocked', action:"lock.lock", icon:"st.locks.lock.unlocked", backgroundColor:"#ffffff" - state "locked", label:'locked', action:"lock.unlock", icon:"st.locks.lock.locked", backgroundColor:"#79b821" + state "locked", label:'locked', action:"lock.unlock", icon:"st.locks.lock.locked", backgroundColor:"#00A0DC" } standardTile("lock", "device.lock", inactiveLabel: false, decoration: "flat") { state "default", label:'lock', action:"lock.lock", icon:"st.locks.lock.locked" diff --git a/devicetypes/capabilities/momentary-capability.src/momentary-capability.groovy b/devicetypes/capabilities/momentary-capability.src/momentary-capability.groovy index 9fa0a6b..688f2e2 100644 --- a/devicetypes/capabilities/momentary-capability.src/momentary-capability.groovy +++ b/devicetypes/capabilities/momentary-capability.src/momentary-capability.groovy @@ -29,7 +29,7 @@ metadata { tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "on" - state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" + state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC" } main "switch" details "switch" diff --git a/devicetypes/capabilities/motion-sensor-capability.src/motion-sensor-capability.groovy b/devicetypes/capabilities/motion-sensor-capability.src/motion-sensor-capability.groovy index 52cc2b9..493173f 100644 --- a/devicetypes/capabilities/motion-sensor-capability.src/motion-sensor-capability.groovy +++ b/devicetypes/capabilities/motion-sensor-capability.src/motion-sensor-capability.groovy @@ -24,7 +24,7 @@ metadata { tiles { standardTile("motion", "device.motion", width: 2, height: 2) { state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff") - state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0") + state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC") } main "motion" details "motion" diff --git a/devicetypes/capabilities/presence-sensor-capability.src/presence-sensor-capability.groovy b/devicetypes/capabilities/presence-sensor-capability.src/presence-sensor-capability.groovy index d90d7fa..219234b 100644 --- a/devicetypes/capabilities/presence-sensor-capability.src/presence-sensor-capability.groovy +++ b/devicetypes/capabilities/presence-sensor-capability.src/presence-sensor-capability.groovy @@ -24,7 +24,7 @@ metadata { tiles { standardTile("presence", "device.presence", width: 2, height: 2) { state("not present", label:'not present', icon:"st.presence.tile.not-present", backgroundColor:"#ffffff") - state("present", label:'present', icon:"st.presence.tile.present", backgroundColor:"#53a7c0") + state("present", label:'present', icon:"st.presence.tile.present", backgroundColor:"#00A0DC") } main "presence" details "presence" diff --git a/devicetypes/capabilities/switch-capability.src/switch-capability.groovy b/devicetypes/capabilities/switch-capability.src/switch-capability.groovy index dc2070f..3b5a01e 100644 --- a/devicetypes/capabilities/switch-capability.src/switch-capability.groovy +++ b/devicetypes/capabilities/switch-capability.src/switch-capability.groovy @@ -31,7 +31,7 @@ metadata { tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" - state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" + state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC" } main "switch" details "switch" diff --git a/devicetypes/capabilities/switch-level-capability.src/switch-level-capability.groovy b/devicetypes/capabilities/switch-level-capability.src/switch-level-capability.groovy index 15230bc..58fc9aa 100644 --- a/devicetypes/capabilities/switch-level-capability.src/switch-level-capability.groovy +++ b/devicetypes/capabilities/switch-level-capability.src/switch-level-capability.groovy @@ -35,8 +35,8 @@ metadata { tiles { standardTile("switch", "device.switch", width: 2, height: 2) { state "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" - state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" - state "turningOn", label:'${name}', icon:"st.switches.switch.on", backgroundColor:"#79b821" + state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff" + state "turningOn", label:'${name}', icon:"st.switches.switch.on", backgroundColor:"#00A0DC" state "turningOff", label:'${name}', icon:"st.switches.switch.off", backgroundColor:"#ffffff" } controlTile("levelSliderControl", "device.level", "slider", height: 2, width: 1, inactiveLabel: false) { diff --git a/devicetypes/capabilities/thermostat-capability.src/thermostat-capability.groovy b/devicetypes/capabilities/thermostat-capability.src/thermostat-capability.groovy index 113b4a5..80cdf98 100644 --- a/devicetypes/capabilities/thermostat-capability.src/thermostat-capability.groovy +++ b/devicetypes/capabilities/thermostat-capability.src/thermostat-capability.groovy @@ -79,8 +79,8 @@ metadata { standardTile("mode", "device.thermostatMode", inactiveLabel: false, decoration: "flat") { state "off", label:'${name}', action:"thermostat.emergencyHeat", backgroundColor:"#ffffff" state "emergencyHeat", label:'${name}', action:"thermostat.heat", backgroundColor:"#e86d13" - state "heat", label:'${name}', action:"thermostat.cool", backgroundColor:"#ffc000" - state "cool", label:'${name}', action:"thermostat.off", backgroundColor:"#269bd2" + state "heat", label:'${name}', action:"thermostat.cool", backgroundColor:"#e86d13" + state "cool", label:'${name}', action:"thermostat.off", backgroundColor:"#00A0DC" } standardTile("fanMode", "device.thermostatFanMode", inactiveLabel: false, decoration: "flat") { state "fanAuto", label:'${name}', action:"thermostat.fanOn", backgroundColor:"#ffffff" diff --git a/devicetypes/capabilities/water-sensor-capability.src/water-sensor-capability.groovy b/devicetypes/capabilities/water-sensor-capability.src/water-sensor-capability.groovy index 5b338e5..567bcf0 100644 --- a/devicetypes/capabilities/water-sensor-capability.src/water-sensor-capability.groovy +++ b/devicetypes/capabilities/water-sensor-capability.src/water-sensor-capability.groovy @@ -24,7 +24,7 @@ metadata { tiles { standardTile("water", "device.water", width: 2, height: 2) { state "dry", icon:"st.alarm.water.dry", backgroundColor:"#ffffff" - state "wet", icon:"st.alarm.water.wet", backgroundColor:"#53a7c0" + state "wet", icon:"st.alarm.water.wet", backgroundColor:"#00A0DC" } main "water" diff --git a/devicetypes/com-obycode/beaconthing.src/beaconthing.groovy b/devicetypes/com-obycode/beaconthing.src/beaconthing.groovy index de1850c..f5bca64 100644 --- a/devicetypes/com-obycode/beaconthing.src/beaconthing.groovy +++ b/devicetypes/com-obycode/beaconthing.src/beaconthing.groovy @@ -37,7 +37,7 @@ metadata { tiles { standardTile("presence", "device.presence", width: 2, height: 2, canChangeBackground: true) { - state("present", labelIcon:"st.presence.tile.present", backgroundColor:"#53a7c0") + state("present", labelIcon:"st.presence.tile.present", backgroundColor:"#00A0DC") state("not present", labelIcon:"st.presence.tile.not-present", backgroundColor:"#ffffff") } valueTile("inRange", "device.inRangeFriendly", inactiveLabel: true, height:1, width:3, decoration: "flat") { diff --git a/devicetypes/com-obycode/obything-music.src/obything-music.groovy b/devicetypes/com-obycode/obything-music.src/obything-music.groovy index b244e3e..878de77 100644 --- a/devicetypes/com-obycode/obything-music.src/obything-music.groovy +++ b/devicetypes/com-obycode/obything-music.src/obything-music.groovy @@ -38,7 +38,7 @@ metadata { // Main standardTile("main", "device.status", width: 1, height: 1, canChangeIcon: true) { state "paused", label:'Paused', action:"music Player.play", icon:"st.Electronics.electronics19", nextState:"playing", backgroundColor:"#ffffff" - state "playing", label:'Playing', action:"music Player.pause", icon:"st.Electronics.electronics19", nextState:"paused", backgroundColor:"#79b821" + state "playing", label:'Playing', action:"music Player.pause", icon:"st.Electronics.electronics19", nextState:"paused", backgroundColor:"#00A0DC" } // Row 1 diff --git a/devicetypes/fibargroup/fibaro-door-window-sensor-zw5-with-temperature.src/fibaro-door-window-sensor-zw5-with-temperature.groovy b/devicetypes/fibargroup/fibaro-door-window-sensor-zw5-with-temperature.src/fibaro-door-window-sensor-zw5-with-temperature.groovy index 56f12ac..47c3f4a 100644 --- a/devicetypes/fibargroup/fibaro-door-window-sensor-zw5-with-temperature.src/fibaro-door-window-sensor-zw5-with-temperature.groovy +++ b/devicetypes/fibargroup/fibaro-door-window-sensor-zw5-with-temperature.src/fibaro-door-window-sensor-zw5-with-temperature.groovy @@ -34,8 +34,8 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"FGK", type:"lighting", width:6, height:4) {//with generic type secondary control text is not displayed in Android app tileAttribute("device.contact", key:"PRIMARY_CONTROL") { - attributeState("open", icon:"st.contact.contact.open", backgroundColor:"#ffa81e") - attributeState("closed", icon:"st.contact.contact.closed", backgroundColor:"#79b821") + attributeState("open", icon:"st.contact.contact.open", backgroundColor:"#e86d13") + attributeState("closed", icon:"st.contact.contact.closed", backgroundColor:"#00a0dc") } tileAttribute("device.tamper", key:"SECONDARY_CONTROL") { @@ -44,7 +44,7 @@ metadata { } } - valueTile("battery", "device.battery", inactiveLabel: false, , width: 2, height: 2, decoration: "flat") { + valueTile("battery", "device.battery", inactiveLabel: false, width: 2, height: 2, decoration: "flat") { state "battery", label:'${currentValue}% battery', unit:"" } diff --git a/devicetypes/fibargroup/fibaro-door-window-sensor-zw5.src/fibaro-door-window-sensor-zw5.groovy b/devicetypes/fibargroup/fibaro-door-window-sensor-zw5.src/fibaro-door-window-sensor-zw5.groovy index f65f838..b05d959 100644 --- a/devicetypes/fibargroup/fibaro-door-window-sensor-zw5.src/fibaro-door-window-sensor-zw5.groovy +++ b/devicetypes/fibargroup/fibaro-door-window-sensor-zw5.src/fibaro-door-window-sensor-zw5.groovy @@ -31,8 +31,8 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"FGK", type:"lighting", width:6, height:4) {//with generic type secondary control text is not displayed in Android app tileAttribute("device.contact", key:"PRIMARY_CONTROL") { - attributeState("open", icon:"st.contact.contact.open", backgroundColor:"#ffa81e") - attributeState("closed", icon:"st.contact.contact.closed", backgroundColor:"#79b821") + attributeState("open", icon:"st.contact.contact.open", backgroundColor:"#e86d13") + attributeState("closed", icon:"st.contact.contact.closed", backgroundColor:"#00a0dc") } tileAttribute("device.tamper", key:"SECONDARY_CONTROL") { @@ -41,7 +41,7 @@ metadata { } } - valueTile("battery", "device.battery", inactiveLabel: false, , width: 2, height: 2, decoration: "flat") { + valueTile("battery", "device.battery", inactiveLabel: false, width: 2, height: 2, decoration: "flat") { state "battery", label:'${currentValue}% battery', unit:"" } 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 4ab0479..c9c5a30 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,28 +21,30 @@ metadata { capability "Tamper Alert" capability "Temperature Measurement" capability "Water Sensor" - - fingerprint deviceId: "0x0701", inClusters: "0x5E, 0x22, 0x85, 0x59, 0x20, 0x80, 0x70, 0x56, 0x5A, 0x7A, 0x72, 0x8E, 0x71, 0x73, 0x98, 0x9C, 0x31, 0x86", outClusters: "" + 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: "" + fingerprint mfr:"010F", prod:"0B01", model:"2002" + fingerprint mfr:"010F", prod:"0B01", model:"1002" } simulator { - } - - tiles(scale: 2) { - multiAttributeTile(name:"FGFS", type:"lighting", width:6, height:4) {//with generic type secondary control text is not displayed in Android app - tileAttribute("device.water", key:"PRIMARY_CONTROL") { - attributeState("dry", icon:"st.alarm.water.dry", backgroundColor:"#79b821") - attributeState("wet", icon:"st.alarm.water.wet", backgroundColor:"#ffa81e") - } - - tileAttribute("device.tamper", key:"SECONDARY_CONTROL") { - attributeState("active", label:'tamper active', backgroundColor:"#53a7c0") - attributeState("inactive", label:'tamper inactive', backgroundColor:"#ffffff") - } - } - - valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2) { + + tiles(scale: 2) { + multiAttributeTile(name:"FGFS", type:"lighting", width:6, height:4) {//with generic type secondary control text is not displayed in Android app + tileAttribute("device.water", key:"PRIMARY_CONTROL") { + attributeState("dry", icon:"st.alarm.water.dry", backgroundColor:"#00a0dc") + attributeState("wet", icon:"st.alarm.water.wet", backgroundColor:"#e86d13") + } + + tileAttribute("device.tamper", key:"SECONDARY_CONTROL") { + attributeState("active", label:'tamper active', backgroundColor:"#00a0dc") + attributeState("inactive", label:'tamper inactive', backgroundColor:"#cccccc") + } + } + + valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2) { state "temperature", label:'${currentValue}°', backgroundColors:[ [value: 31, color: "#153591"], @@ -54,22 +56,22 @@ metadata { [value: 96, color: "#bc2323"] ] } - - valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { - state "battery", label:'${currentValue}% battery', unit:"" - } - - main "FGFS" - details(["FGFS","battery", "temperature"]) - } + + valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { + state "battery", label:'${currentValue}% battery', unit:"" + } + + main "FGFS" + details(["FGFS","battery", "temperature"]) + } } // parse events into attributes def parse(String description) { log.debug "Parsing '${description}'" def result = [] - - if (description.startsWith("Err 106")) { + + if (description.startsWith("Err 106")) { if (state.sec) { result = createEvent(descriptionText:description, displayed:false) } else { @@ -84,13 +86,13 @@ def parse(String description) { } else if (description == "updated") { return null } else { - def cmd = zwave.parse(description, [0x31: 5, 0x56: 1, 0x71: 3, 0x72:2, 0x80: 1, 0x84: 2, 0x85: 2, 0x86: 1, 0x98: 1]) + def cmd = zwave.parse(description, [0x31: 5, 0x56: 1, 0x71: 3, 0x72:2, 0x80: 1, 0x84: 2, 0x85: 2, 0x86: 1, 0x98: 1]) - if (cmd) { - log.debug "Parsed '${cmd}'" - zwaveEvent(cmd) - } - } + if (cmd) { + log.debug "Parsed '${cmd}'" + zwaveEvent(cmd) + } + } } //security @@ -107,7 +109,7 @@ def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulat //crc16 def zwaveEvent(physicalgraph.zwave.commands.crc16encapv1.Crc16Encap cmd) { - def versions = [0x31: 5, 0x72: 2, 0x80: 1] + def versions = [0x31: 5, 0x72: 2, 0x80: 1] 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) @@ -121,105 +123,124 @@ def zwaveEvent(physicalgraph.zwave.commands.crc16encapv1.Crc16Encap cmd) def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd) { def event = createEvent(descriptionText: "${device.displayName} woke up", displayed: false) - def cmds = [] - cmds << encap(zwave.batteryV1.batteryGet()) - cmds << "delay 500" - cmds << encap(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 1, scale: 0)) - cmds << "delay 1200" - cmds << encap(zwave.wakeUpV1.wakeUpNoMoreInformation()) - [event, response(cmds)] + def cmds = [] + // cmds << encap(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 1, scale: 0)) + // cmds << "delay 500" + cmds << encap(zwave.batteryV1.batteryGet()) + [event, response(cmds)] } def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) { log.debug "manufacturerId: ${cmd.manufacturerId}" - log.debug "manufacturerName: ${cmd.manufacturerName}" - log.debug "productId: ${cmd.productId}" - log.debug "productTypeId: ${cmd.productTypeId}" + log.debug "manufacturerName: ${cmd.manufacturerName}" + log.debug "productId: ${cmd.productId}" + log.debug "productTypeId: ${cmd.productTypeId}" } def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.DeviceSpecificReport cmd) { log.debug "deviceIdData: ${cmd.deviceIdData}" - log.debug "deviceIdDataFormat: ${cmd.deviceIdDataFormat}" - log.debug "deviceIdDataLengthIndicator: ${cmd.deviceIdDataLengthIndicator}" - log.debug "deviceIdType: ${cmd.deviceIdType}" - - if (cmd.deviceIdType == 1 && cmd.deviceIdDataFormat == 1) {//serial number in binary format + log.debug "deviceIdDataFormat: ${cmd.deviceIdDataFormat}" + log.debug "deviceIdDataLengthIndicator: ${cmd.deviceIdDataLengthIndicator}" + log.debug "deviceIdType: ${cmd.deviceIdType}" + + if (cmd.deviceIdType == 1 && cmd.deviceIdDataFormat == 1) { //serial number in binary format String serialNumber = "h'" - - cmd.deviceIdData.each{ data -> - serialNumber += "${String.format("%02X", data)}" - } - - updateDataValue("serialNumber", serialNumber) - log.debug "${device.displayName} - serial number: ${serialNumber}" - } + + cmd.deviceIdData.each{ data -> + serialNumber += "${String.format("%02X", data)}" + } + + updateDataValue("serialNumber", serialNumber) + log.debug "${device.displayName} - serial number: ${serialNumber}" + } + + def response_cmds = [] + if (!device.currentState("temperature")) { + response_cmds << encap(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 1, scale: 0)) + } + if (!getDataValue("version") && !zwaveInfo.ver) { + log.debug "Requesting Version Report" + response_cmds << "delay 500" + response_cmds << encap(zwave.versionV1.versionGet()) + } + response_cmds << "delay 1000" + response_cmds << encap(zwave.wakeUpV2.wakeUpNoMoreInformation()) + [[:], response(response_cmds)] } -def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) { - updateDataValue("version", "${cmd.applicationVersion}.${cmd.applicationSubVersion}") - log.debug "applicationVersion: ${cmd.applicationVersion}" - log.debug "applicationSubVersion: ${cmd.applicationSubVersion}" - log.debug "zWaveLibraryType: ${cmd.zWaveLibraryType}" - log.debug "zWaveProtocolVersion: ${cmd.zWaveProtocolVersion}" - log.debug "zWaveProtocolSubVersion: ${cmd.zWaveProtocolSubVersion}" +def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) { + updateDataValue("version", "${cmd.applicationVersion}.${cmd.applicationSubVersion}") + log.debug "applicationVersion: ${cmd.applicationVersion}" + log.debug "applicationSubVersion: ${cmd.applicationSubVersion}" + log.debug "zWaveLibraryType: ${cmd.zWaveLibraryType}" + log.debug "zWaveProtocolVersion: ${cmd.zWaveProtocolVersion}" + log.debug "zWaveProtocolSubVersion: ${cmd.zWaveProtocolSubVersion}" } def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) { + def result = [] def map = [:] map.name = "battery" map.value = cmd.batteryLevel == 255 ? 1 : cmd.batteryLevel.toString() map.unit = "%" - map.displayed = true - createEvent(map) + + result << createEvent(map) + + if (!getDataValue("serialNumber")) { + result << response(encap(zwave.manufacturerSpecificV2.deviceSpecificGet())) + } else { + result << response(encap(zwave.wakeUpV2.wakeUpNoMoreInformation())) + } + result } def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd) { def map = [:] - if (cmd.notificationType == 5) { - switch (cmd.event) { - case 2: - map.name = "water" - map.value = "wet" - map.descriptionText = "${device.displayName} is ${map.value}" - break - - case 0: - map.name = "water" - map.value = "dry" - map.descriptionText = "${device.displayName} is ${map.value}" - break - } - } else if (cmd.notificationType == 7) { - switch (cmd.event) { - case 0: - map.name = "tamper" - map.value = "inactive" - map.descriptionText = "${device.displayName}: tamper alarm has been deactivated" + if (cmd.notificationType == 5) { + switch (cmd.event) { + case 2: + map.name = "water" + map.value = "wet" + map.descriptionText = "${device.displayName} is ${map.value}" break - - case 3: - map.name = "tamper" - map.value = "active" - map.descriptionText = "${device.displayName}: tamper alarm activated" - break - } - } - - createEvent(map) + + case 0: + map.name = "water" + map.value = "dry" + map.descriptionText = "${device.displayName} is ${map.value}" + break + } + } else if (cmd.notificationType == 7) { + switch (cmd.event) { + case 0: + map.name = "tamper" + map.value = "inactive" + map.descriptionText = "${device.displayName}: tamper alarm has been deactivated" + break + + case 3: + map.name = "tamper" + map.value = "active" + map.descriptionText = "${device.displayName}: tamper alarm activated" + break + } + } + + createEvent(map) } def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv5.SensorMultilevelReport cmd) { def map = [:] if (cmd.sensorType == 1) { - // temperature - def cmdScale = cmd.scale == 1 ? "F" : "C" - map.value = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmdScale, cmd.precision) - map.unit = getTemperatureScale() - map.name = "temperature" - map.displayed = true + // temperature + def cmdScale = cmd.scale == 1 ? "F" : "C" + map.value = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmdScale, cmd.precision) + map.unit = getTemperatureScale() + map.name = "temperature" + map.displayed = true } - - createEvent(map) + + createEvent(map) } def zwaveEvent(physicalgraph.zwave.commands.deviceresetlocallyv1.DeviceResetLocallyNotification cmd) { @@ -228,19 +249,18 @@ def zwaveEvent(physicalgraph.zwave.commands.deviceresetlocallyv1.DeviceResetLoca def configure() { log.debug "Executing 'configure'" - - def cmds = [] - - cmds += zwave.wakeUpV2.wakeUpIntervalSet(seconds:21600, nodeid: zwaveHubNodeId)//FGFS' default wake up interval - cmds += zwave.manufacturerSpecificV2.manufacturerSpecificGet() - cmds += zwave.manufacturerSpecificV2.deviceSpecificGet() - cmds += zwave.versionV1.versionGet() - cmds += zwave.batteryV1.batteryGet() - cmds += zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 1, scale: 0) - cmds += zwave.associationV2.associationSet(groupingIdentifier:1, nodeId: [zwaveHubNodeId]) - cmds += zwave.wakeUpV2.wakeUpNoMoreInformation() + // Device wakes up every 4 hours, this interval of 8h 2m allows us to miss one wakeup notification before marking offline + sendEvent(name: "checkInterval", value: 8 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) - encapSequence(cmds, 500) + // default initial state + sendEvent(name: "water", value: "dry") + + def cmds = [] + + cmds << zwave.associationV2.associationSet(groupingIdentifier:1, nodeId: [zwaveHubNodeId]) + cmds << zwave.batteryV1.batteryGet() // other queries sent as response to BatteryReport + + encapSequence(cmds, 200) } private secure(physicalgraph.zwave.Command cmd) { @@ -249,7 +269,7 @@ private secure(physicalgraph.zwave.Command cmd) { private crc16(physicalgraph.zwave.Command cmd) { //zwave.crc16EncapV1.crc16Encap().encapsulate(cmd).format() - "5601${cmd.format()}0000" + "5601${cmd.format()}0000" } private encapSequence(commands, delay=200) { @@ -257,13 +277,10 @@ private encapSequence(commands, delay=200) { } private encap(physicalgraph.zwave.Command cmd) { - def secureClasses = [0x20, 0x5A, 0x70, 0x71, 0x84, 0x85, 0x8E, 0x9C] - - //todo: check if secure inclusion was successful - //if not do not send security-encapsulated command - if (secureClasses.find{ it == cmd.commandClassId }) { - secure(cmd) - } else { - crc16(cmd) - } -} \ No newline at end of file + if (zwaveInfo.zw && !zwaveInfo.zw.contains("s")) { + // Secure inclusion failed + crc16(cmd) + } else { + secure(cmd) + } +} 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 ae882ed..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: "" } @@ -38,8 +39,8 @@ metadata { } tileAttribute("device.tamper", key:"SECONDARY_CONTROL") { - attributeState("active", label:'tamper active', backgroundColor:"#53a7c0") - attributeState("inactive", label:'tamper inactive', backgroundColor:"#ffffff") + attributeState("active", label:'tamper active', backgroundColor:"#00a0dc") + attributeState("inactive", label:'tamper inactive', backgroundColor:"#cccccc") } } @@ -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/johnrucker/coopboss-h3vx.src/coopboss-h3vx.groovy b/devicetypes/johnrucker/coopboss-h3vx.src/coopboss-h3vx.groovy index 510c4ef..e398e09 100644 --- a/devicetypes/johnrucker/coopboss-h3vx.src/coopboss-h3vx.groovy +++ b/devicetypes/johnrucker/coopboss-h3vx.src/coopboss-h3vx.groovy @@ -112,10 +112,10 @@ metadata { multiAttributeTile(name:"dtlsDoorCtrl", type:"generic", width:6, height:4) {tileAttribute("device.doorState", key: "PRIMARY_CONTROL") { attributeState "unknown", label: '${name}', action:"openDoor", icon: "st.secondary.tools", nextState:"Sent" - attributeState "open", label: '${name}', action:"closeDoor", icon: "st.doors.garage.garage-open", backgroundColor: "#0000ff", nextState:"Sent" - attributeState "opening", label: '${name}', action:"closeDoor", icon: "st.doors.garage.garage-opening", backgroundColor: "#ffa81e" - attributeState "closed", label: '${name}', action:"openDoor", icon: "st.doors.garage.garage-closed", backgroundColor: "#79b821", nextState:"Sent" - attributeState "closing", label: '${name}', action:"openDoor", icon: "st.doors.garage.garage-closing", backgroundColor: "#ffa81e" + attributeState "open", label: '${name}', action:"closeDoor", icon: "st.doors.garage.garage-open", backgroundColor: "#00A0DC", nextState:"Sent" + attributeState "opening", label: '${name}', action:"closeDoor", icon: "st.doors.garage.garage-opening", backgroundColor: "#00A0DC" + attributeState "closed", label: '${name}', action:"openDoor", icon: "st.doors.garage.garage-closed", backgroundColor: "#ffffff", nextState:"Sent" + attributeState "closing", label: '${name}', action:"openDoor", icon: "st.doors.garage.garage-closing", backgroundColor: "#ffffff" attributeState "jammed", label: '${name}', action:"closeDoorHiI", icon: "st.doors.garage.garage-open", backgroundColor: "#ff0000", nextState:"Sent" attributeState "forced close", label: "forced", action:"openDoor", icon: "st.doors.garage.garage-closed", backgroundColor: "#ff8000", nextState:"Sent" attributeState "fault", label: 'FAULT', action:"openDoor", icon: "st.secondary.tools", backgroundColor: "#ff0000", nextState:"Sent" diff --git a/devicetypes/juano2310/jawbone-user.src/jawbone-user.groovy b/devicetypes/juano2310/jawbone-user.src/jawbone-user.groovy index 4d15594..125f38c 100644 --- a/devicetypes/juano2310/jawbone-user.src/jawbone-user.groovy +++ b/devicetypes/juano2310/jawbone-user.src/jawbone-user.groovy @@ -24,7 +24,7 @@ metadata { tiles { standardTile("sleeping", "device.sleeping", width: 1, height: 1, canChangeIcon: false, canChangeBackground: false) { state("sleeping", label: "Sleeping", icon:"st.Bedroom.bedroom12", backgroundColor:"#ffffff") - state("not sleeping", label: "Awake", icon:"st.Health & Wellness.health12", backgroundColor:"#79b821") + state("not sleeping", label: "Awake", icon:"st.Health & Wellness.health12", backgroundColor:"#00A0DC") } standardTile("steps", "device.steps", width: 2, height: 2, canChangeIcon: false, canChangeBackground: false) { state("steps", label: '${currentValue} Steps', icon:"st.Health & Wellness.health11", backgroundColor:"#ffffff") diff --git a/devicetypes/keen-home/keen-home-smart-vent.src/keen-home-smart-vent.groovy b/devicetypes/keen-home/keen-home-smart-vent.src/keen-home-smart-vent.groovy index 9f64b2c..93703ef 100644 --- a/devicetypes/keen-home/keen-home-smart-vent.src/keen-home-smart-vent.groovy +++ b/devicetypes/keen-home/keen-home-smart-vent.src/keen-home-smart-vent.groovy @@ -40,10 +40,10 @@ metadata { // UI tile definitions tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { - state "on", action: "switch.off", icon: "st.vents.vent-open-text", backgroundColor: "#53a7c0" + state "on", action: "switch.off", icon: "st.vents.vent-open-text", backgroundColor: "#00a0dc" state "off", action: "switch.on", icon: "st.vents.vent-closed", backgroundColor: "#ffffff" - state "obstructed", action: "clearObstruction", icon: "st.vents.vent-closed", backgroundColor: "#ff0000" - state "clearing", action: "", icon: "st.vents.vent-closed", backgroundColor: "#ffff33" + state "obstructed", action: "clearObstruction", icon: "st.vents.vent-closed", backgroundColor: "#e86d13" + state "clearing", action: "", icon: "st.vents.vent-closed", backgroundColor: "#ffffff" } controlTile("levelSliderControl", "device.level", "slider", height: 1, width: 2, inactiveLabel: false) { state "level", action:"switch level.setLevel" diff --git a/devicetypes/plaidsystems/spruce-controller.src/spruce-controller.groovy b/devicetypes/plaidsystems/spruce-controller.src/spruce-controller.groovy index 0025def..baf2f1a 100644 --- a/devicetypes/plaidsystems/spruce-controller.src/spruce-controller.groovy +++ b/devicetypes/plaidsystems/spruce-controller.src/spruce-controller.groovy @@ -122,13 +122,13 @@ metadata { state "raintoday", label: 'Rain Today', icon: "st.custom.wuk.nt_chancerain" state "rainy", label: 'Previous Rain', icon: "st.custom.wuk.nt_chancerain" state "raintom", label: 'Rain Tomorrow', icon: "st.custom.wuk.nt_chancerain" - state "donewweek", label: 'Spruce Finished', icon: "st.Outdoor.outdoor5", backgroundColor: "#52c435" + state "donewweek", label: 'Spruce Finished', icon: "st.Outdoor.outdoor5", backgroundColor: "#00A0DC" state "skipping", label: 'Skip Today', icon: "st.Outdoor.outdoor20", backgroundColor: "#36cfe3" state "moisture", label: '', icon: "st.Weather.weather2", backgroundColor: "#36cfe3" - state "pause", label: 'PAUSE', icon: "st.contact.contact.open", backgroundColor: "#f2a51f" + state "pause", label: 'PAUSE', icon: "st.contact.contact.open", backgroundColor: "#e86d13" state "active", label: 'Active', icon: "st.Outdoor.outdoor12", backgroundColor: "#3DC72E" state "season", label: 'Seasonal Adjustment', icon: "st.Outdoor.outdoor17", backgroundColor: "#ffb900" - state "disable", label: 'Disabled', icon: "st.secondary.off", backgroundColor: "#888888" + state "disable", label: 'Disabled', icon: "st.secondary.off", backgroundColor: "#cccccc" state "warning", label: '', icon: "st.categories.damageAndDanger", backgroundColor: "#ffff7f" state "alarm", label: 'Alarm', icon: "st.categories.damageAndDanger", backgroundColor: "#f9240c" } @@ -144,67 +144,67 @@ metadata { } standardTile("switch1", "device.switch1") { state "z1off", label: '1', action: "z1on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z1on", label: '1', action: "z1off", icon: "st.valves.water.open", backgroundColor: "#46c2e8" + state "z1on", label: '1', action: "z1off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" } standardTile("switch2", "device.switch2") { state "z2off", label: '2', action: "z2on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z2on", label: '2', action: "z2off", icon: "st.valves.water.open", backgroundColor: "#46c2e8" + state "z2on", label: '2', action: "z2off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" } standardTile("switch3", "device.switch3", inactiveLabel: false) { state "z3off", label: '3', action: "z3on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z3on", label: '3', action: "z3off", icon: "st.valves.water.open", backgroundColor: "#46c2e8" + state "z3on", label: '3', action: "z3off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" } standardTile("switch4", "device.switch4", inactiveLabel: false) { state "z4off", label: '4', action: "z4on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z4on", label: '4', action: "z4off", icon: "st.valves.water.open", backgroundColor: "#46c2e8" + state "z4on", label: '4', action: "z4off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" } standardTile("switch5", "device.switch5", inactiveLabel: false) { state "z5off", label: '5', action: "z5on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z5on", label: '5', action: "z5off", icon: "st.valves.water.open", backgroundColor: "#46c2e8" + state "z5on", label: '5', action: "z5off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" } standardTile("switch6", "device.switch6", inactiveLabel: false) { state "z6off", label: '6', action: "z6on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z6on", label: '6', action: "z6off", icon: "st.valves.water.open", backgroundColor: "#46c2e8" + state "z6on", label: '6', action: "z6off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" } standardTile("switch7", "device.switch7", inactiveLabel: false) { state "z7off", label: '7', action: "z7on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z7on", label: '7', action: "z7off", icon: "st.valves.water.open", backgroundColor: "#46c2e8" + state "z7on", label: '7', action: "z7off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" } standardTile("switch8", "device.switch8", inactiveLabel: false) { state "z8off", label: '8', action: "z8on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z8on", label: '8', action: "z8off", icon: "st.valves.water.open", backgroundColor: "#46c2e8" + state "z8on", label: '8', action: "z8off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" } standardTile("switch9", "device.switch9", inactiveLabel: false) { state "z9off", label: '9', action: "z9on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z9on", label: '9', action: "z9off", icon: "st.valves.water.open", backgroundColor: "#46c2e8" + state "z9on", label: '9', action: "z9off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" } standardTile("switch10", "device.switch10", inactiveLabel: false) { state "z10off", label: '10', action: "z10on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z10on", label: '10', action: "z10off", icon: "st.valves.water.open", backgroundColor: "#46c2e8" + state "z10on", label: '10', action: "z10off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" } standardTile("switch11", "device.switch11", inactiveLabel: false) { state "z11off", label: '11', action: "z11on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z11on", label: '11', action: "z11off", icon: "st.valves.water.open", backgroundColor: "#46c2e8" + state "z11on", label: '11', action: "z11off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" } standardTile("switch12", "device.switch12", inactiveLabel: false) { state "z12off", label: '12', action: "z12on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z12on", label: '12', action: "z12off", icon: "st.valves.water.open", backgroundColor: "#46c2e8" + state "z12on", label: '12', action: "z12off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" } standardTile("switch13", "device.switch13", inactiveLabel: false) { state "z13off", label: '13', action: "z13on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z13on", label: '13', action: "z13off", icon: "st.valves.water.open", backgroundColor: "#46c2e8" + state "z13on", label: '13', action: "z13off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" } standardTile("switch14", "device.switch14", inactiveLabel: false) { state "z14off", label: '14', action: "z14on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z14on", label: '14', action: "z14off", icon: "st.valves.water.open", backgroundColor: "#46c2e8" + state "z14on", label: '14', action: "z14off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" } standardTile("switch15", "device.switch15", inactiveLabel: false) { state "z15off", label: '15', action: "z15on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z15on", label: '15', action: "z15off", icon: "st.valves.water.open", backgroundColor: "#46c2e8" + state "z15on", label: '15', action: "z15off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" } standardTile("switch16", "device.switch16", inactiveLabel: false) { state "z16off", label: '16', action: "z16on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z16on", label: '16', action: "z16off", icon: "st.valves.water.open", backgroundColor: "#46c2e8" + state "z16on", label: '16', action: "z16off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" } standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") { state "default", action: "refresh", icon:"st.secondary.refresh" diff --git a/devicetypes/roomieremote-agent/simple-sync.src/simple-sync.groovy b/devicetypes/roomieremote-agent/simple-sync.src/simple-sync.groovy index b54321a..053172c 100644 --- a/devicetypes/roomieremote-agent/simple-sync.src/simple-sync.groovy +++ b/devicetypes/roomieremote-agent/simple-sync.src/simple-sync.groovy @@ -22,7 +22,7 @@ metadata { standardTile("mainTile", "device.status", width: 1, height: 1, icon: "st.Entertainment.entertainment11") { - state "default", label: "Simple Sync", icon: "st.Home.home2", backgroundColor: "#55A7FF" + state "default", label: "Simple Sync", icon: "st.Home.home2", backgroundColor: "#00a0dc" } def detailTiles = ["mainTile"] diff --git a/devicetypes/smartthings/aeon-illuminator-module.src/aeon-illuminator-module.groovy b/devicetypes/smartthings/aeon-illuminator-module.src/aeon-illuminator-module.groovy index 2f2c747..ab84256 100644 --- a/devicetypes/smartthings/aeon-illuminator-module.src/aeon-illuminator-module.groovy +++ b/devicetypes/smartthings/aeon-illuminator-module.src/aeon-illuminator-module.groovy @@ -47,9 +47,9 @@ metadata { tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { - state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" + state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff" state "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" - state "turningOn", label:'${name}', icon:"st.switches.switch.on", backgroundColor:"#79b821" + state "turningOn", label:'${name}', icon:"st.switches.switch.on", backgroundColor:"#00A0DC" state "turningOff", label:'${name}', icon:"st.switches.switch.off", backgroundColor:"#ffffff" } controlTile("levelSliderControl", "device.level", "slider", height: 2, width: 1, inactiveLabel: false) { diff --git a/devicetypes/smartthings/aeon-key-fob.src/aeon-key-fob.groovy b/devicetypes/smartthings/aeon-key-fob.src/aeon-key-fob.groovy index 40f5403..a782169 100644 --- a/devicetypes/smartthings/aeon-key-fob.src/aeon-key-fob.groovy +++ b/devicetypes/smartthings/aeon-key-fob.src/aeon-key-fob.groovy @@ -37,14 +37,14 @@ metadata { tiles { standardTile("button", "device.button", width: 2, height: 2) { state "default", label: "", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#ffffff" - state "button 1 pushed", label: "pushed #1", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#79b821" - state "button 2 pushed", label: "pushed #2", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#79b821" - state "button 3 pushed", label: "pushed #3", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#79b821" - state "button 4 pushed", label: "pushed #4", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#79b821" - state "button 1 held", label: "held #1", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#ffa81e" - state "button 2 held", label: "held #2", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#ffa81e" - state "button 3 held", label: "held #3", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#ffa81e" - state "button 4 held", label: "held #4", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#ffa81e" + state "button 1 pushed", label: "pushed #1", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#00A0DC" + state "button 2 pushed", label: "pushed #2", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#00A0DC" + state "button 3 pushed", label: "pushed #3", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#00A0DC" + state "button 4 pushed", label: "pushed #4", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#00A0DC" + state "button 1 held", label: "held #1", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#e86d13" + state "button 2 held", label: "held #2", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#e86d13" + state "button 3 held", label: "held #3", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#e86d13" + state "button 4 held", label: "held #4", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#e86d13" } valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") { state "battery", label:'${currentValue}% battery', unit:"" diff --git a/devicetypes/smartthings/aeon-led-bulb.src/aeon-led-bulb.groovy b/devicetypes/smartthings/aeon-led-bulb.src/aeon-led-bulb.groovy index fbcbc40..eecaa62 100644 --- a/devicetypes/smartthings/aeon-led-bulb.src/aeon-led-bulb.groovy +++ b/devicetypes/smartthings/aeon-led-bulb.src/aeon-led-bulb.groovy @@ -37,9 +37,9 @@ metadata { } standardTile("switch", "device.switch", width: 1, height: 1, canChangeIcon: true) { - state "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + state "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00a0dc", nextState:"turningOff" state "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - state "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + state "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00a0dc", nextState:"turningOff" state "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" } standardTile("reset", "device.reset", inactiveLabel: false, decoration: "flat") { diff --git a/devicetypes/smartthings/aeon-multisensor-6.src/aeon-multisensor-6.groovy b/devicetypes/smartthings/aeon-multisensor-6.src/aeon-multisensor-6.groovy index 4b194db..02f5ccc 100644 --- a/devicetypes/smartthings/aeon-multisensor-6.src/aeon-multisensor-6.groovy +++ b/devicetypes/smartthings/aeon-multisensor-6.src/aeon-multisensor-6.groovy @@ -82,8 +82,8 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"motion", type: "generic", width: 6, height: 4){ tileAttribute ("device.motion", key: "PRIMARY_CONTROL") { - attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0" - attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff" + attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC" + attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc" } } valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2) { diff --git a/devicetypes/smartthings/aeon-multisensor-gen5.src/.st-ignore b/devicetypes/smartthings/aeon-multisensor-gen5.src/.st-ignore new file mode 100644 index 0000000..f78b46e --- /dev/null +++ b/devicetypes/smartthings/aeon-multisensor-gen5.src/.st-ignore @@ -0,0 +1,2 @@ +.st-ignore +README.md diff --git a/devicetypes/smartthings/aeon-multisensor-gen5.src/README.md b/devicetypes/smartthings/aeon-multisensor-gen5.src/README.md new file mode 100644 index 0000000..62a8f9a --- /dev/null +++ b/devicetypes/smartthings/aeon-multisensor-gen5.src/README.md @@ -0,0 +1,43 @@ +# Aeon Multisensor Gen5 + +Cloud Execution + +Works with: + +* [Aeon Labs MultiSensor (Gen 5)](https://www.smartthings.com/works-with-smartthings/sensors/aeon-labs-multisensor-gen-5) + +## Table of contents + +* [Capabilities](#capabilities) +* [Health](#device-health) +* [Troubleshooting](#troubleshooting) + +## Capabilities + +* **Motion Sensor** - can detect motion +* **Temperature Measurement** - defines device measures current temperature +* **Relative Humidity Measurement** - allow reading the relative humidity from devices that support it +* **Illuminance Measurement** - gives the illuminance reading from devices that support it +* **Configuration** - _configure()_ command called when device is installed or device preferences updated +* **Sensor** - detects sensor events +* **Battery** - defines device uses a battery +* **Health Check** - indicates ability to get device health notifications + + +## Device Health + +Aeon Labs MultiSensor (Gen 5) is polled by the hub. +As of hubCore version 0.14.38 the hub sends up reports every 15 minutes regardless of whether the state changed. +Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*15 + 2)mins = 32 mins. +Not to mention after going OFFLINE when the device is plugged back in, it might take a considerable amount of time for +the device to appear as ONLINE again. This is because if this listening device does not respond to two poll requests in a row, +it is not polled for 5 minutes by the hub. This can delay up the process of being marked ONLINE by quite some time. + +* __32min__ checkInterval + +## Troubleshooting + +If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range. +Pairing needs to be tried again by placing the device closer to the hub. +Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link: +* [Aeon Labs MultiSensor (Gen 5) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206157226-Aeon-Labs-MultiSensor-Gen-5-) \ No newline at end of file diff --git a/devicetypes/smartthings/aeon-multisensor-gen5.src/aeon-multisensor-gen5.groovy b/devicetypes/smartthings/aeon-multisensor-gen5.src/aeon-multisensor-gen5.groovy index 04888d3..358f2a5 100644 --- a/devicetypes/smartthings/aeon-multisensor-gen5.src/aeon-multisensor-gen5.groovy +++ b/devicetypes/smartthings/aeon-multisensor-gen5.src/aeon-multisensor-gen5.groovy @@ -20,10 +20,12 @@ metadata { capability "Configuration" capability "Sensor" capability "Battery" + capability "Health Check" command "configureAfterSecure" fingerprint deviceId: "0x0701", inClusters: "0x5E,0x86,0x72,0x59,0x85,0x73,0x71,0x84,0x80,0x30,0x31,0x70,0x98,0x7A", outClusters:"0x5A" + fingerprint mfr:"0086", prod:"0102", model:"004A", deviceJoinName: "Aeon Labs MultiSensor (Gen 5)" } simulator { @@ -64,8 +66,8 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"motion", type: "generic", width: 6, height: 4){ tileAttribute ("device.motion", key: "PRIMARY_CONTROL") { - attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0" - attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff" + attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00a0dc" + attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc" } } valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2) { @@ -98,6 +100,11 @@ metadata { } } +def updated(){ +// Device-Watch simply pings if no device events received for 32min(checkInterval) + sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) +} + def parse(String description) { def result = null @@ -244,6 +251,13 @@ def configureAfterSecure() { secureSequence(request) + ["delay 20000", zwave.wakeUpV1.wakeUpNoMoreInformation().format()] } +/** + * PING is used by Device-Watch in attempt to reach the Device + * */ +def ping() { + secure(zwave.batteryV1.batteryGet()) +} + def configure() { // log.debug "configure()" //["delay 30000"] + secure(zwave.securityV1.securityCommandsSupportedGet()) diff --git a/devicetypes/smartthings/aeon-multisensor.src/aeon-multisensor.groovy b/devicetypes/smartthings/aeon-multisensor.src/aeon-multisensor.groovy index 5d6de58..fa1fa37 100644 --- a/devicetypes/smartthings/aeon-multisensor.src/aeon-multisensor.groovy +++ b/devicetypes/smartthings/aeon-multisensor.src/aeon-multisensor.groovy @@ -59,8 +59,8 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"motion", type: "generic", width: 6, height: 4){ tileAttribute ("device.motion", key: "PRIMARY_CONTROL") { - attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0" - attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff" + attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00a0dc" + attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc" } } valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2) { diff --git a/devicetypes/smartthings/aeon-outlet.src/aeon-outlet.groovy b/devicetypes/smartthings/aeon-outlet.src/aeon-outlet.groovy index e356fe6..1123df1 100644 --- a/devicetypes/smartthings/aeon-outlet.src/aeon-outlet.groovy +++ b/devicetypes/smartthings/aeon-outlet.src/aeon-outlet.groovy @@ -45,7 +45,7 @@ metadata { // tile definitions tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { - state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" + state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00a0dc" state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" } valueTile("energy", "device.energy", decoration: "flat") { diff --git a/devicetypes/smartthings/aeon-secure-smart-energy-switch-uk.src/aeon-secure-smart-energy-switch-uk.groovy b/devicetypes/smartthings/aeon-secure-smart-energy-switch-uk.src/aeon-secure-smart-energy-switch-uk.groovy index 70cfee6..d7e6eac 100644 --- a/devicetypes/smartthings/aeon-secure-smart-energy-switch-uk.src/aeon-secure-smart-energy-switch-uk.groovy +++ b/devicetypes/smartthings/aeon-secure-smart-energy-switch-uk.src/aeon-secure-smart-energy-switch-uk.groovy @@ -53,7 +53,7 @@ metadata { // tile definitions tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { - state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" + state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC" state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" } valueTile("power", "device.power", decoration: "flat") { diff --git a/devicetypes/smartthings/aeon-siren.src/.st-ignore b/devicetypes/smartthings/aeon-siren.src/.st-ignore new file mode 100644 index 0000000..f78b46e --- /dev/null +++ b/devicetypes/smartthings/aeon-siren.src/.st-ignore @@ -0,0 +1,2 @@ +.st-ignore +README.md diff --git a/devicetypes/smartthings/aeon-siren.src/README.md b/devicetypes/smartthings/aeon-siren.src/README.md new file mode 100644 index 0000000..f4e0166 --- /dev/null +++ b/devicetypes/smartthings/aeon-siren.src/README.md @@ -0,0 +1,37 @@ +# Aeon Siren + +Cloud Execution + +Works with: + +* [Aeon Labs Siren (Gen 5)](https://www.smartthings.com/works-with-smartthings/aeon-labs/aeon-labs-siren-gen-5) + +## Table of contents + +* [Capabilities](#capabilities) +* [Health](#device-health) + +## Capabilities + +* **Actuator** - represents that a Device has commands +* **Alarm** - allows for interacting with devices that serve as alarms +* **Switch** - can detect state (possible values: on/off) +* **Health Check** - indicates ability to get device health notifications + +## Device Health + +Aeon Labs Siren (Gen 5) is polled by the hub. +As of hubCore version 0.14.38 the hub sends up reports every 15 minutes regardless of whether the state changed. +Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*15 + 2)mins = 32 mins. +Not to mention after going OFFLINE when the device is plugged back in, it might take a considerable amount of time for +the device to appear as ONLINE again. This is because if this listening device does not respond to two poll requests in a row, +it is not polled for 5 minutes by the hub. This can delay up the process of being marked ONLINE by quite some time. + +* __32min__ checkInterval + +## Troubleshooting + +If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range. +Pairing needs to be tried again by placing the device closer to the hub. +Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link: +* [Aeon Labs Siren (Gen 5) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/204555240-Aeon-Labs-Siren-Gen-5-) \ No newline at end of file diff --git a/devicetypes/smartthings/aeon-siren.src/aeon-siren.groovy b/devicetypes/smartthings/aeon-siren.src/aeon-siren.groovy index a0fafb3..8b961aa 100644 --- a/devicetypes/smartthings/aeon-siren.src/aeon-siren.groovy +++ b/devicetypes/smartthings/aeon-siren.src/aeon-siren.groovy @@ -20,10 +20,11 @@ metadata { capability "Actuator" capability "Alarm" capability "Switch" + capability "Health Check" command "test" - fingerprint deviceId: "0x1005", inClusters: "0x5E,0x98" + fingerprint deviceId: "0x1005", inClusters: "0x5E,0x98", deviceJoinName: "Aeon Labs Siren (Gen 5)" } simulator { @@ -58,6 +59,9 @@ metadata { } def updated() { +// Device-Watch simply pings if no device events received for 32min(checkInterval) + sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) + if(!state.sound) state.sound = 1 if(!state.volume) state.volume = 3 @@ -148,3 +152,10 @@ def test() { private secure(physicalgraph.zwave.Command cmd) { zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format() } + +/** + * PING is used by Device-Watch in attempt to reach the Device + * */ +def ping() { + secure(zwave.basicV1.basicGet()) +} \ No newline at end of file diff --git a/devicetypes/smartthings/aeon-smartstrip.src/aeon-smartstrip.groovy b/devicetypes/smartthings/aeon-smartstrip.src/aeon-smartstrip.groovy index cfd1330..ecb698f 100644 --- a/devicetypes/smartthings/aeon-smartstrip.src/aeon-smartstrip.groovy +++ b/devicetypes/smartthings/aeon-smartstrip.src/aeon-smartstrip.groovy @@ -60,7 +60,7 @@ metadata { // tile definitions tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { - state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" + state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00a0dc" state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" } valueTile("power", "device.power", decoration: "flat") { @@ -78,7 +78,7 @@ metadata { (1..4).each { n -> standardTile("switch$n", "switch$n", canChangeIcon: true) { - state "on", label: '${name}', action: "off$n", icon: "st.switches.switch.on", backgroundColor: "#79b821" + state "on", label: '${name}', action: "off$n", icon: "st.switches.switch.on", backgroundColor: "#00a0dc" state "off", label: '${name}', action: "on$n", icon: "st.switches.switch.off", backgroundColor: "#ffffff" } valueTile("power$n", "power$n", decoration: "flat") { diff --git a/devicetypes/smartthings/arrival-sensor-ha.src/arrival-sensor-ha.groovy b/devicetypes/smartthings/arrival-sensor-ha.src/arrival-sensor-ha.groovy index 3175764..9498e69 100644 --- a/devicetypes/smartthings/arrival-sensor-ha.src/arrival-sensor-ha.groovy +++ b/devicetypes/smartthings/arrival-sensor-ha.src/arrival-sensor-ha.groovy @@ -11,7 +11,6 @@ * for the specific language governing permissions and limitations under the License. * */ - metadata { definition (name: "Arrival Sensor HA", namespace: "smartthings", author: "SmartThings") { capability "Tone" @@ -40,7 +39,7 @@ metadata { tiles { standardTile("presence", "device.presence", width: 2, height: 2, canChangeBackground: true) { - state "present", labelIcon:"st.presence.tile.present", backgroundColor:"#53a7c0" + state "present", labelIcon:"st.presence.tile.present", backgroundColor:"#00a0dc" state "not present", labelIcon:"st.presence.tile.not-present", backgroundColor:"#ffffff" } standardTile("beep", "device.beep", decoration: "flat") { @@ -60,7 +59,7 @@ def updated() { } def configure() { - def cmds = zigbee.configureReporting(0x0001, 0x0020, 0x20, 20, 20, 0x01) + def cmds = zigbee.batteryConfig(20, 20, 0x01) log.debug "configure -- cmds: ${cmds}" return cmds } @@ -152,7 +151,7 @@ private handlePresenceEvent(present) { private startTimer() { log.debug "Scheduling periodic timer" - schedule("0 * * * * ?", checkPresenceCallback) + runEvery1Minute("checkPresenceCallback") } private stopTimer() { diff --git a/devicetypes/smartthings/arrival-sensor.src/arrival-sensor.groovy b/devicetypes/smartthings/arrival-sensor.src/arrival-sensor.groovy index 5b87cc1..4fbd53d 100644 --- a/devicetypes/smartthings/arrival-sensor.src/arrival-sensor.groovy +++ b/devicetypes/smartthings/arrival-sensor.src/arrival-sensor.groovy @@ -42,8 +42,8 @@ metadata { tiles { standardTile("presence", "device.presence", width: 2, height: 2, canChangeBackground: true) { - state "present", labelIcon:"st.presence.tile.present", backgroundColor:"#53a7c0" - state "not present", labelIcon:"st.presence.tile.not-present", backgroundColor:"#ebeef2" + state "present", labelIcon:"st.presence.tile.present", backgroundColor:"#00a0dc" + state "not present", labelIcon:"st.presence.tile.not-present", backgroundColor:"#ffffff" } standardTile("beep", "device.beep", decoration: "flat") { state "beep", label:'', action:"tone.beep", icon:"st.secondary.beep", backgroundColor:"#ffffff" diff --git a/devicetypes/smartthings/bose-soundtouch.src/bose-soundtouch.groovy b/devicetypes/smartthings/bose-soundtouch.src/bose-soundtouch.groovy index 090be56..5aafc08 100644 --- a/devicetypes/smartthings/bose-soundtouch.src/bose-soundtouch.groovy +++ b/devicetypes/smartthings/bose-soundtouch.src/bose-soundtouch.groovy @@ -67,10 +67,10 @@ metadata { } standardTile("switch", "device.switch", width: 1, height: 1, canChangeIcon: true) { - state "on", label: '${name}', action: "forceOff", icon: "st.Electronics.electronics16", backgroundColor: "#79b821", nextState:"turningOff" + state "on", label: '${name}', action: "forceOff", icon: "st.Electronics.electronics16", backgroundColor: "#00a0dc", nextState:"turningOff" state "turningOff", label:'TURNING OFF', icon:"st.Electronics.electronics16", backgroundColor:"#ffffff" state "off", label: '${name}', action: "forceOn", icon: "st.Electronics.electronics16", backgroundColor: "#ffffff", nextState:"turningOn" - state "turningOn", label:'TURNING ON', icon:"st.Electronics.electronics16", backgroundColor:"#79b821" + state "turningOn", label:'TURNING ON', icon:"st.Electronics.electronics16", backgroundColor:"#00a0dc" } valueTile("1", "device.station1", decoration: "flat", canChangeIcon: false) { state "station1", label:'${currentValue}', action:"preset1" diff --git a/devicetypes/smartthings/centralite-thermostat.src/centralite-thermostat.groovy b/devicetypes/smartthings/centralite-thermostat.src/centralite-thermostat.groovy index a92839f..a2e6bda 100644 --- a/devicetypes/smartthings/centralite-thermostat.src/centralite-thermostat.groovy +++ b/devicetypes/smartthings/centralite-thermostat.src/centralite-thermostat.groovy @@ -55,13 +55,13 @@ metadata { state "fanOn", label:'${name}', action:"thermostat.setThermostatFanMode" } controlTile("heatSliderControl", "device.heatingSetpoint", "slider", height: 1, width: 2, inactiveLabel: false) { - state "setHeatingSetpoint", action:"thermostat.setHeatingSetpoint", backgroundColor:"#d04e00" + state "setHeatingSetpoint", action:"thermostat.setHeatingSetpoint", backgroundColor:"#e86d13" } valueTile("heatingSetpoint", "device.heatingSetpoint", inactiveLabel: false, decoration: "flat") { state "heat", label:'${currentValue}° heat', unit:"F", backgroundColor:"#ffffff" } controlTile("coolSliderControl", "device.coolingSetpoint", "slider", height: 1, width: 2, inactiveLabel: false) { - state "setCoolingSetpoint", action:"thermostat.setCoolingSetpoint", backgroundColor: "#1e9cbb" + state "setCoolingSetpoint", action:"thermostat.setCoolingSetpoint", backgroundColor: "#00a0dc" } valueTile("coolingSetpoint", "device.coolingSetpoint", inactiveLabel: false, decoration: "flat") { state "cool", label:'${currentValue}° cool', unit:"F", backgroundColor:"#ffffff" @@ -81,51 +81,47 @@ metadata { // parse events into attributes def parse(String description) { log.debug "Parse description $description" - def map = [:] - if (description?.startsWith("read attr -")) { - def descMap = parseDescriptionAsMap(description) - log.debug "Desc Map: $descMap" - if (descMap.cluster == "0201" && descMap.attrId == "0000") { + List result = [] + def descMap = zigbee.parseDescriptionAsMap(description) + log.debug "Desc Map: $descMap" + List attrData = [[cluster: descMap.cluster ,attrId: descMap.attrId, value: descMap.value]] + descMap.additionalAttrs.each { + attrData << [cluster: descMap.cluster, attrId: it.attrId, value: it.value] + } + attrData.each { + def map = [:] + if (it.cluster == "0201" && it.attrId == "0000") { log.debug "TEMP" map.name = "temperature" - map.value = getTemperature(descMap.value) + map.value = getTemperature(it.value) map.unit = temperatureScale - } else if (descMap.cluster == "0201" && descMap.attrId == "0011") { + } else if (it.cluster == "0201" && it.attrId == "0011") { log.debug "COOLING SETPOINT" map.name = "coolingSetpoint" - map.value = getTemperature(descMap.value) + map.value = getTemperature(it.value) map.unit = temperatureScale - } else if (descMap.cluster == "0201" && descMap.attrId == "0012") { + } else if (it.cluster == "0201" && it.attrId == "0012") { log.debug "HEATING SETPOINT" map.name = "heatingSetpoint" - map.value = getTemperature(descMap.value) + map.value = getTemperature(it.value) map.unit = temperatureScale - } else if (descMap.cluster == "0201" && descMap.attrId == "001c") { + } else if (it.cluster == "0201" && it.attrId == "001c") { log.debug "MODE" map.name = "thermostatMode" - map.value = getModeMap()[descMap.value] - } else if (descMap.cluster == "0202" && descMap.attrId == "0000") { + map.value = getModeMap()[it.value] + } else if (it.cluster == "0202" && it.attrId == "0000") { log.debug "FAN MODE" map.name = "thermostatFanMode" - map.value = getFanModeMap()[descMap.value] + map.value = getFanModeMap()[it.value] } + if (map) { + result << createEvent(map) + } + log.debug "Parse returned $map" } - - def result = null - if (map) { - result = createEvent(map) - } - log.debug "Parse returned $map" return result } -def parseDescriptionAsMap(description) { - (description - "read attr - ").split(",").inject([:]) { map, param -> - def nameAndValue = param.split(":") - map += [(nameAndValue[0].trim()):nameAndValue[1].trim()] - } -} - def getModeMap() { [ "00":"off", "03":"cool", diff --git a/devicetypes/smartthings/cooper-rf9500.src/cooper-rf9500.groovy b/devicetypes/smartthings/cooper-rf9500.src/cooper-rf9500.groovy index 5e22791..cace3cc 100644 --- a/devicetypes/smartthings/cooper-rf9500.src/cooper-rf9500.groovy +++ b/devicetypes/smartthings/cooper-rf9500.src/cooper-rf9500.groovy @@ -36,7 +36,7 @@ metadata { tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { state "off", label: '${name}', action: "switch.on", icon: "st.Home.home30", backgroundColor: "#ffffff" - state "on", label: '${name}', action: "switch.off", icon: "st.Home.home30", backgroundColor: "#79b821" + state "on", label: '${name}', action: "switch.off", icon: "st.Home.home30", backgroundColor: "#00a0dc" } standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") { state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh" diff --git a/devicetypes/smartthings/cree-bulb.src/cree-bulb.groovy b/devicetypes/smartthings/cree-bulb.src/cree-bulb.groovy index 26fa1b9..e04a47a 100644 --- a/devicetypes/smartthings/cree-bulb.src/cree-bulb.groovy +++ b/devicetypes/smartthings/cree-bulb.src/cree-bulb.groovy @@ -23,6 +23,7 @@ metadata { capability "Switch" capability "Switch Level" capability "Health Check" + capability "Light" fingerprint profileId: "C05E", inClusters: "0000,0003,0004,0005,0006,0008,1000", outClusters: "0000,0019" } @@ -42,9 +43,9 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn" } tileAttribute ("device.level", key: "SLIDER_CONTROL") { @@ -82,7 +83,7 @@ def on() { } def setLevel(value) { - zigbee.setLevel(value) + ["delay 500"] + zigbee.levelRefresh() //adding refresh because of ZLL bulb not conforming to send-me-a-report + zigbee.setLevel(value) + zigbee.onOffRefresh() + zigbee.levelRefresh() //adding refresh because of ZLL bulb not conforming to send-me-a-report } /** diff --git a/devicetypes/smartthings/ct100-thermostat.src/ct100-thermostat.groovy b/devicetypes/smartthings/ct100-thermostat.src/ct100-thermostat.groovy index 1737fed..93203fd 100644 --- a/devicetypes/smartthings/ct100-thermostat.src/ct100-thermostat.groovy +++ b/devicetypes/smartthings/ct100-thermostat.src/ct100-thermostat.groovy @@ -81,13 +81,13 @@ metadata { state "fanCirculate", label:'${name}', action:"switchFanMode" } controlTile("heatSliderControl", "device.heatingSetpoint", "slider", height: 1, width: 2, inactiveLabel: false) { - state "setHeatingSetpoint", action:"quickSetHeat", backgroundColor:"#d04e00" + state "setHeatingSetpoint", action:"quickSetHeat", backgroundColor:"#e86d13" } valueTile("heatingSetpoint", "device.heatingSetpoint", inactiveLabel: false, decoration: "flat") { state "heat", label:'${currentValue}° heat', backgroundColor:"#ffffff" } controlTile("coolSliderControl", "device.coolingSetpoint", "slider", height: 1, width: 2, inactiveLabel: false) { - state "setCoolingSetpoint", action:"quickSetCool", backgroundColor: "#1e9cbb" + state "setCoolingSetpoint", action:"quickSetCool", backgroundColor: "#00a0dc" } valueTile("coolingSetpoint", "device.coolingSetpoint", inactiveLabel: false, decoration: "flat") { state "cool", label:'${currentValue}° cool', backgroundColor:"#ffffff" diff --git a/devicetypes/smartthings/danalock.src/danalock.groovy b/devicetypes/smartthings/danalock.src/danalock.groovy index 0cbc330..31834c1 100644 --- a/devicetypes/smartthings/danalock.src/danalock.groovy +++ b/devicetypes/smartthings/danalock.src/danalock.groovy @@ -33,10 +33,10 @@ metadata { tiles { standardTile("toggle", "device.lock", width: 2, height: 2) { - state "locked", label:'locked', action:"lock.unlock", icon:"st.locks.lock.locked", backgroundColor:"#79b821", nextState:"unlocking" + state "locked", label:'locked', action:"lock.unlock", icon:"st.locks.lock.locked", backgroundColor:"#00a0dc", nextState:"unlocking" state "unlocked", label:'unlocked', action:"lock.lock", icon:"st.locks.lock.unlocked", backgroundColor:"#ffffff", nextState:"locking" state "unknown", label:"unknown", action:"lock.lock", icon:"st.locks.lock.unknown", backgroundColor:"#ffffff", nextState:"locking" - state "locking", label:'locking', icon:"st.locks.lock.locked", backgroundColor:"#79b821" + state "locking", label:'locking', icon:"st.locks.lock.locked", backgroundColor:"#00a0dc" state "unlocking", label:'unlocking', icon:"st.locks.lock.unlocked", backgroundColor:"#ffffff" } standardTile("lock", "device.lock", inactiveLabel: false, decoration: "flat") { diff --git a/devicetypes/smartthings/dimmer-switch.src/README.md b/devicetypes/smartthings/dimmer-switch.src/README.md index 71a27b6..595ff8d 100644 --- a/devicetypes/smartthings/dimmer-switch.src/README.md +++ b/devicetypes/smartthings/dimmer-switch.src/README.md @@ -7,6 +7,8 @@ Works with: * [GE Z-Wave In-Wall Smart Dimmer (GE 12724)](http://products.z-wavealliance.org/products/1197) * [GE Z-Wave In-Wall Smart Dimmer (Toggle) (GE 12729)](http://products.z-wavealliance.org/products/1201) * [GE Z-Wave Plug-in Smart Dimmer (GE 12718)](http://products.z-wavealliance.org/products/1191) +* [GE 1,000-Watt In-Wall Smart Dimmer Switch (GE 12725)](http://products.z-wavealliance.org/products/1198) +* [GE In-Wall Smart Fan Control (GE 12730)](http://products.z-wavealliance.org/products/1202) ## Table of contents @@ -27,7 +29,7 @@ Works with: ## Device Health -Z-Wave Smart Dimmers (In-Wall, In-Wall(Toggle), Plug-In) are polled by the hub. +Z-Wave Smart Dimmers (In-Wall, In-Wall(Toggle), Plug-In), 1000-watt In-Wall Smart Dimmer Switch and In-Wall Smart Fan Control are polled by the hub. As of hubCore version 0.14.38 the hub sends up reports every 15 minutes regardless of whether the state changed. Check-in interval = 32 mins. Not to mention after going OFFLINE when the device is plugged back in, it might take a considerable amount of time for @@ -44,4 +46,6 @@ Instructions related to pairing, resetting and removing the device from SmartThi * [General Z-Wave Dimmer/Switch Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/200955890-Troubleshooting-GE-in-wall-switch-or-dimmer-won-t-respond-to-commands-or-automations-Z-Wave-) * [GE Z-Wave In-Wall Smart Dimmer (GE 12724) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/200902600-GE-In-Wall-Paddle-Dimmer-Switch-GE-12724-Z-Wave-) * [GE Z-Wave In-Wall Smart Dimmer (Toggle) (GE 12729) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/207568463-GE-In-Wall-Smart-Toggle-Dimmer-GE-12729-Z-Wave-) -* [GE Z-Wave Plug-in Smart Dimmer (GE 12718) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/202088474-GE-Plug-In-Smart-Dimmer-GE-12718-Z-Wave-) \ No newline at end of file +* [GE Z-Wave Plug-in Smart Dimmer (GE 12718) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/202088474-GE-Plug-In-Smart-Dimmer-GE-12718-Z-Wave-) +* [GE 1,000-Watt In-Wall Smart Dimmer Switch (GE 12725) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/200879274) +* [GE In-Wall Smart Fan Control (GE 12730) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/200879274) \ No newline at end of file diff --git a/devicetypes/smartthings/dimmer-switch.src/dimmer-switch.groovy b/devicetypes/smartthings/dimmer-switch.src/dimmer-switch.groovy index 98510ca..ef0fddd 100644 --- a/devicetypes/smartthings/dimmer-switch.src/dimmer-switch.groovy +++ b/devicetypes/smartthings/dimmer-switch.src/dimmer-switch.groovy @@ -21,10 +21,12 @@ metadata { capability "Refresh" capability "Sensor" capability "Health Check" + capability "Light" - fingerprint mfr:"0063", prod:"4457", deviceJoinName: "Z-Wave Wall Dimmer" - fingerprint mfr:"0063", prod:"4944", deviceJoinName: "Z-Wave Wall Dimmer" - fingerprint mfr:"0063", prod:"5044", deviceJoinName: "Z-Wave Plug-In Dimmer" + fingerprint mfr:"0063", prod:"4457", deviceJoinName: "GE In-Wall Smart Dimmer " + fingerprint mfr:"0063", prod:"4944", deviceJoinName: "GE In-Wall Smart Dimmer " + fingerprint mfr:"0063", prod:"5044", deviceJoinName: "GE Plug-In Smart Dimmer " + fingerprint mfr:"0063", prod:"4944", model:"3034", deviceJoinName: "GE In-Wall Smart Fan Control" } simulator { @@ -52,9 +54,9 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00a0dc", nextState:"turningOff" attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00a0dc", nextState:"turningOff" attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" } tileAttribute ("device.level", key: "SLIDER_CONTROL") { diff --git a/devicetypes/smartthings/ecobee-sensor.src/ecobee-sensor.groovy b/devicetypes/smartthings/ecobee-sensor.src/ecobee-sensor.groovy index 381f6fc..312513b 100644 --- a/devicetypes/smartthings/ecobee-sensor.src/ecobee-sensor.groovy +++ b/devicetypes/smartthings/ecobee-sensor.src/ecobee-sensor.groovy @@ -47,8 +47,8 @@ metadata { } standardTile("motion", "device.motion") { - state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff") - state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0") + state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc") + state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC") } standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat") { diff --git a/devicetypes/smartthings/econet-vent.src/econet-vent.groovy b/devicetypes/smartthings/econet-vent.src/econet-vent.groovy index e2651b7..56a3249 100644 --- a/devicetypes/smartthings/econet-vent.src/econet-vent.groovy +++ b/devicetypes/smartthings/econet-vent.src/econet-vent.groovy @@ -53,7 +53,7 @@ metadata { tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { - state "on", action:"switch.off", icon:"st.vents.vent-open-text", backgroundColor:"#53a7c0" + state "on", action:"switch.off", icon:"st.vents.vent-open-text", backgroundColor:"#00a0dc" state "off", action:"switch.on", icon:"st.vents.vent-closed", backgroundColor:"#ffffff" } valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") { diff --git a/devicetypes/smartthings/everspring-flood-sensor.src/everspring-flood-sensor.groovy b/devicetypes/smartthings/everspring-flood-sensor.src/everspring-flood-sensor.groovy index f97fdde..3c72f29 100644 --- a/devicetypes/smartthings/everspring-flood-sensor.src/everspring-flood-sensor.groovy +++ b/devicetypes/smartthings/everspring-flood-sensor.src/everspring-flood-sensor.groovy @@ -33,7 +33,7 @@ metadata { multiAttributeTile(name:"water", type: "generic", width: 6, height: 4){ tileAttribute ("device.water", key: "PRIMARY_CONTROL") { attributeState "dry", icon:"st.alarm.water.dry", backgroundColor:"#ffffff" - attributeState "wet", icon:"st.alarm.water.wet", backgroundColor:"#53a7c0" + attributeState "wet", icon:"st.alarm.water.wet", backgroundColor:"#00a0dc" } } valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) { diff --git a/devicetypes/smartthings/fibaro-dimmer.src/fibaro-dimmer.groovy b/devicetypes/smartthings/fibaro-dimmer.src/fibaro-dimmer.groovy index 1c9081a..39ecee2 100644 --- a/devicetypes/smartthings/fibaro-dimmer.src/fibaro-dimmer.groovy +++ b/devicetypes/smartthings/fibaro-dimmer.src/fibaro-dimmer.groovy @@ -56,9 +56,9 @@ metadata { tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { - state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" + state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00a0dc", nextState:"turningOff" state "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" - state "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" + state "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00a0dc", nextState:"turningOff" state "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" } standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") { 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..cd69d4a 100644 --- a/devicetypes/smartthings/fibaro-flood-sensor.src/fibaro-flood-sensor.groovy +++ b/devicetypes/smartthings/fibaro-flood-sensor.src/fibaro-flood-sensor.groovy @@ -1,12 +1,12 @@ /** * Device Type Definition File * - * Device Type: Fibaro Flood Sensor - * File Name: fibaro-flood-sensor.groovy - * Initial Release: 2014-12-10 - * @author: Todd Wackford - * Email: todd@wackford.net - * @version: 1.0 + * Device Type: Fibaro Flood Sensor + * File Name: fibaro-flood-sensor.groovy + * Initial Release: 2014-12-10 + * @author: Todd Wackford + * Email: todd@wackford.net + * @version: 1.0 * * Copyright 2014 SmartThings * @@ -26,8 +26,8 @@ * 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(["water", "temperature", "tamper"]) - * details(["water", "temperature", "battery", "tamper"]) + * main(["water", "temperature", "tamper"]) + * details(["water", "temperature", "battery", "tamper"]) * * @param none * @@ -39,13 +39,18 @@ metadata { capability "Temperature Measurement" capability "Configuration" capability "Battery" - - command "resetParams2StDefaults" - command "listCurrentParams" - command "updateZwaveParam" - command "test" - + capability "Health Check" + capability "Sensor" + + command "resetParams2StDefaults" + command "listCurrentParams" + command "updateZwaveParam" + command "test" + fingerprint deviceId: "0xA102", inClusters: "0x30,0x9C,0x60,0x85,0x8E,0x72,0x70,0x86,0x80,0x84" + fingerprint mfr:"010F", prod:"0000", model:"2002" + fingerprint mfr:"010F", prod:"0000", model:"1002" + fingerprint mfr:"010F", prod:"0B00", model:"1001" } simulator { @@ -72,7 +77,7 @@ metadata { tiles { standardTile("water", "device.water", width: 2, height: 2) { state "dry", icon:"st.alarm.water.dry", backgroundColor:"#ffffff" - state "wet", icon:"st.alarm.water.wet", backgroundColor:"#53a7c0" + state "wet", icon:"st.alarm.water.wet", backgroundColor:"#00a0dc" } valueTile("temperature", "device.temperature", inactiveLabel: false) { state "temperature", label:'${currentValue}°', @@ -86,9 +91,9 @@ metadata { [value: 96, color: "#bc2323"] ] } - standardTile("tamper", "device.tamper") { - state("secure", label:"secure", icon:"st.locks.lock.locked", backgroundColor:"#ffffff") - state("tampered", label:"tampered", icon:"st.locks.lock.unlocked", backgroundColor:"#53a7c0") + standardTile("tamper", "device.tamper") { + state("secure", label:"secure", icon:"st.locks.lock.locked", backgroundColor:"#ffffff") + state("tampered", label:"tampered", icon:"st.locks.lock.unlocked", backgroundColor:"#00a0dc") } valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") { state "battery", label:'${currentValue}% battery', unit:"" @@ -106,26 +111,17 @@ metadata { def parse(String description) { def result = [] - - if (description == "updated") { - if (!state.MSR) { - result << response(zwave.wakeUpV1.wakeUpIntervalSet(seconds: 60*60, nodeid:zwaveHubNodeId)) - result << response(zwave.manufacturerSpecificV2.manufacturerSpecificGet()) - } - } else { - def cmd = zwave.parse(description, [0x31: 2, 0x30: 1, 0x70: 2, 0x71: 1, 0x84: 1, 0x80: 1, 0x9C: 1, 0x72: 2, 0x56: 2, 0x60: 3]) - - if (cmd) { - result += zwaveEvent(cmd) //createEvent(zwaveEvent(cmd)) - } - } - - result << response(zwave.batteryV1.batteryGet().format()) - - if ( result[0] != null ) { + + def cmd = zwave.parse(description, [0x31: 2, 0x30: 1, 0x70: 2, 0x71: 1, 0x84: 1, 0x80: 1, 0x9C: 1, 0x72: 2, 0x56: 2, 0x60: 3]) + + if (cmd) { + result += zwaveEvent(cmd) //createEvent(zwaveEvent(cmd)) + } + + if ( result[0] != null ) { log.debug "Parse returned ${result}" result - } + } } @@ -142,10 +138,9 @@ def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd) { def result = [createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)] if (!isConfigured()) { // we're still in the process of configuring a newly joined device - result += lateConfigure(true) + result << lateConfigure(true) } else { - result += response(zwave.wakeUpV1.wakeUpNoMoreInformation()) - log.debug "We're done with WakeUp!" + result << response(zwave.wakeUpV1.wakeUpNoMoreInformation()) } result } @@ -153,7 +148,7 @@ def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd) { def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv2.SensorMultilevelReport cmd) { def map = [:] - + switch (cmd.sensorType) { case 1: // temperature @@ -184,7 +179,7 @@ def zwaveEvent(physicalgraph.zwave.commands.sensorbinaryv1.SensorBinaryReport cm def map = [:] map.value = cmd.sensorValue ? "active" : "inactive" map.name = "acceleration" - + if (map.value == "active") { map.descriptionText = "$device.displayName detected vibration" } @@ -199,49 +194,49 @@ def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport } def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) { - log.debug "BasicSet with CMD = ${cmd}" - - if (!isConfigured()) { - def result = [] - def map = [:] - - map.name = "water" + log.debug "BasicSet with CMD = ${cmd}" + + if (!isConfigured()) { + def result = [] + def map = [:] + + map.name = "water" map.value = cmd.value ? "wet" : "dry" map.descriptionText = "${device.displayName} is ${map.value}" - - // If we are getting a BasicSet, and isConfigured == false, then we are likely NOT properly configured. - result += lateConfigure(true) - - result << createEvent(map) - - result - } + + // If we are getting a BasicSet, and isConfigured == false, then we are likely NOT properly configured. + result += lateConfigure(true) + + result << createEvent(map) + + result + } } def zwaveEvent(physicalgraph.zwave.commands.sensoralarmv1.SensorAlarmReport cmd) { def map = [:] - + if (cmd.sensorType == 0x05) { map.name = "water" map.value = cmd.sensorState ? "wet" : "dry" map.descriptionText = "${device.displayName} is ${map.value}" - - log.debug "CMD = SensorAlarmReport: ${cmd}" - setConfigured() - } else if ( cmd.sensorType == 0) { - map.name = "tamper" - map.isStateChange = true - map.value = cmd.sensorState ? "tampered" : "secure" - map.descriptionText = "${device.displayName} has been tampered with" - runIn(30, "resetTamper") //device does not send alarm cancelation - - } else if ( cmd.sensorType == 1) { - map.name = "tamper" - map.value = cmd.sensorState ? "tampered" : "secure" - map.descriptionText = "${device.displayName} has been tampered with" - runIn(30, "resetTamper") //device does not send alarm cancelation - + + log.debug "CMD = SensorAlarmReport: ${cmd}" + setConfigured() + } else if ( cmd.sensorType == 0) { + map.name = "tamper" + map.isStateChange = true + map.value = cmd.sensorState ? "tampered" : "secure" + map.descriptionText = "${device.displayName} has been tampered with" + runIn(30, "resetTamper") //device does not send alarm cancelation + + } else if ( cmd.sensorType == 1) { + map.name = "tamper" + map.value = cmd.sensorState ? "tampered" : "secure" + map.descriptionText = "${device.displayName} has been tampered with" + runIn(30, "resetTamper") //device does not send alarm cancelation + } else { map.descriptionText = "${device.displayName}: ${cmd}" } @@ -250,10 +245,10 @@ def zwaveEvent(physicalgraph.zwave.commands.sensoralarmv1.SensorAlarmReport cmd) def resetTamper() { def map = [:] - map.name = "tamper" - map.value = "secure" - map.descriptionText = "$device.displayName is secure" - sendEvent(map) + map.name = "tamper" + map.value = "secure" + map.descriptionText = "$device.displayName is secure" + sendEvent(map) } def zwaveEvent(physicalgraph.zwave.Command cmd) { @@ -267,10 +262,10 @@ def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerS def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId) log.debug "msr: $msr" device.updateDataValue(["MSR", msr]) - - if ( msr == "010F-0B00-2001" ) { //this is the msr and device type for the fibaro flood sensor - result += lateConfigure(true) - } + + if ( msr == "010F-0B00-2001" ) { //this is the msr and device type for the fibaro flood sensor + result += lateConfigure(true) + } result << createEvent(descriptionText: "$device.displayName MSR: $msr", isStateChange: false) result @@ -282,17 +277,17 @@ def setConfigured() { def isConfigured() { Boolean configured = device.getDataValue(["configured"]) as Boolean - - return configured + + return configured } def lateConfigure(setConf = False) { def res = response(configure()) - - if (setConf) - setConfigured() - - return res + + if (setConf) + setConfigured() + + return res } /** @@ -304,26 +299,34 @@ def lateConfigure(setConf = False) { */ def configure() { log.debug "Configuring Device..." - def cmds = [] - - // send associate to group 2 to get alarm data - cmds << zwave.associationV2.associationSet(groupingIdentifier:2, nodeId:[zwaveHubNodeId]).format() - - cmds << zwave.configurationV1.configurationSet(configurationValue: [255], parameterNumber: 5, size: 1).format() - - // send associate to group 3 to get sensor data reported only to hub - cmds << zwave.associationV2.associationSet(groupingIdentifier:3, nodeId:[zwaveHubNodeId]).format() + // Device wakes up every 4 hours, this interval allows us to miss one wakeup notification before marking offline + sendEvent(name: "checkInterval", value: 8 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) - // temp hysteresis set to .5 degrees celcius - cmds << zwave.configurationV1.configurationSet(configurationValue: [0,50], parameterNumber: 12, size: 2).format() - cmds << zwave.configurationV1.configurationGet(parameterNumber: 12).format() + // default initial state + sendEvent(name: "water", value: "dry") + + def cmds = [] + + // send associate to group 2 to get alarm data + cmds << zwave.associationV2.associationSet(groupingIdentifier:2, nodeId:[zwaveHubNodeId]).format() + + cmds << zwave.configurationV1.configurationSet(configurationValue: [255], parameterNumber: 5, size: 1).format() + + // send associate to group 3 to get sensor data reported only to hub + cmds << zwave.associationV2.associationSet(groupingIdentifier:3, nodeId:[zwaveHubNodeId]).format() // reporting frequency of temps and battery set to one hour cmds << zwave.configurationV1.configurationSet(configurationValue: [0,60*60], parameterNumber: 10, size: 2).format() - cmds << zwave.configurationV1.configurationGet(parameterNumber: 10).format() - - cmds << zwave.wakeUpV1.wakeUpNoMoreInformation().format() - + // cmds << zwave.configurationV1.configurationGet(parameterNumber: 10).format() + + // temp hysteresis set to .5 degrees celcius + cmds << zwave.configurationV1.configurationSet(configurationValue: [0,50], parameterNumber: 12, size: 2).format() + // cmds << zwave.configurationV1.configurationGet(parameterNumber: 12).format() + + cmds << zwave.batteryV1.batteryGet().format() + + cmds << zwave.wakeUpV1.wakeUpNoMoreInformation().format() + delayBetween(cmds, 100) } @@ -349,18 +352,18 @@ def test() { * @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 (triple-click?)" - log.debug "Updating ${device.displayName} parameter number '${pNumber}' with value '${pValue}' with size of '${pSize}'" + 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 (triple-click?)" + 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) - } + cmds << zwave.configurationV1.configurationSet(configurationValue: pValue, parameterNumber: pNumber, size: pSize).format() + cmds << zwave.configurationV1.configurationGet(parameterNumber: pNumber).format() + delayBetween(cmds, 1000) + } } /** @@ -377,26 +380,26 @@ def updateZwaveParam(params) { 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: [3], parameterNumber: 2, 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: [1], parameterNumber: 9, size: 1).format() - cmds << zwave.configurationV1.configurationSet(configurationValue: [0,60*60], parameterNumber: 10, size: 2).format() - cmds << zwave.configurationV1.configurationSet(configurationValue: [0,50], parameterNumber: 12, size: 2).format() - cmds << zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 13, size: 1).format() - cmds << zwave.configurationV1.configurationSet(configurationValue: [5,220], parameterNumber: 50, size: 2).format() - cmds << zwave.configurationV1.configurationSet(configurationValue: [13,172], parameterNumber: 51, size: 2).format() - cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0,0,225], parameterNumber: 61, size: 4).format() - cmds << zwave.configurationV1.configurationSet(configurationValue: [0,255,0,0], parameterNumber: 62, size: 4).format() - cmds << zwave.configurationV1.configurationSet(configurationValue: [2], parameterNumber: 63, size: 1).format() - cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 73, size: 2).format() - cmds << zwave.configurationV1.configurationSet(configurationValue: [2], parameterNumber: 74, size: 1).format() - cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 75, size: 2).format() - cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 76, size: 2).format() - cmds << zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 77, size: 1).format() - - delayBetween(cmds, 1200) + cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 1, size: 2).format() + cmds << zwave.configurationV1.configurationSet(configurationValue: [3], parameterNumber: 2, 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: [1], parameterNumber: 9, size: 1).format() + cmds << zwave.configurationV1.configurationSet(configurationValue: [0,60*60], parameterNumber: 10, size: 2).format() + cmds << zwave.configurationV1.configurationSet(configurationValue: [0,50], parameterNumber: 12, size: 2).format() + cmds << zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 13, size: 1).format() + cmds << zwave.configurationV1.configurationSet(configurationValue: [5,220], parameterNumber: 50, size: 2).format() + cmds << zwave.configurationV1.configurationSet(configurationValue: [13,172], parameterNumber: 51, size: 2).format() + cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0,0,225], parameterNumber: 61, size: 4).format() + cmds << zwave.configurationV1.configurationSet(configurationValue: [0,255,0,0], parameterNumber: 62, size: 4).format() + cmds << zwave.configurationV1.configurationSet(configurationValue: [2], parameterNumber: 63, size: 1).format() + cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 73, size: 2).format() + cmds << zwave.configurationV1.configurationSet(configurationValue: [2], parameterNumber: 74, size: 1).format() + cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 75, size: 2).format() + cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 76, size: 2).format() + cmds << zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 77, size: 1).format() + + delayBetween(cmds, 1200) } /** @@ -413,25 +416,25 @@ def resetParams2StDefaults() { 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: 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: 50).format() - cmds << zwave.configurationV1.configurationGet(parameterNumber: 51).format() - cmds << zwave.configurationV1.configurationGet(parameterNumber: 61).format() - cmds << zwave.configurationV1.configurationGet(parameterNumber: 62).format() - cmds << zwave.configurationV1.configurationGet(parameterNumber: 63).format() - cmds << zwave.configurationV1.configurationGet(parameterNumber: 73).format() - cmds << zwave.configurationV1.configurationGet(parameterNumber: 74).format() - cmds << zwave.configurationV1.configurationGet(parameterNumber: 75).format() - cmds << zwave.configurationV1.configurationGet(parameterNumber: 76).format() - cmds << zwave.configurationV1.configurationGet(parameterNumber: 77).format() - + cmds << zwave.configurationV1.configurationGet(parameterNumber: 1).format() + cmds << zwave.configurationV1.configurationGet(parameterNumber: 2).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: 50).format() + cmds << zwave.configurationV1.configurationGet(parameterNumber: 51).format() + cmds << zwave.configurationV1.configurationGet(parameterNumber: 61).format() + cmds << zwave.configurationV1.configurationGet(parameterNumber: 62).format() + cmds << zwave.configurationV1.configurationGet(parameterNumber: 63).format() + cmds << zwave.configurationV1.configurationGet(parameterNumber: 73).format() + cmds << zwave.configurationV1.configurationGet(parameterNumber: 74).format() + cmds << zwave.configurationV1.configurationGet(parameterNumber: 75).format() + cmds << zwave.configurationV1.configurationGet(parameterNumber: 76).format() + cmds << zwave.configurationV1.configurationGet(parameterNumber: 77).format() + delayBetween(cmds, 1200) } 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..c07a019 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" @@ -81,8 +82,8 @@ tiles { standardTile("motion", "device.motion", width: 2, height: 2) { - state "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0" - state "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff" + state "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00a0dc" + state "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc" } valueTile("temperature", "device.temperature", inactiveLabel: false) { state "temperature", label:'${currentValue}°', @@ -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/devicetypes/smartthings/fibaro-rgbw-controller.src/fibaro-rgbw-controller.groovy b/devicetypes/smartthings/fibaro-rgbw-controller.src/fibaro-rgbw-controller.groovy index cd40f10..4385edc 100644 --- a/devicetypes/smartthings/fibaro-rgbw-controller.src/fibaro-rgbw-controller.groovy +++ b/devicetypes/smartthings/fibaro-rgbw-controller.src/fibaro-rgbw-controller.groovy @@ -89,9 +89,9 @@ state "whiteLevel", action:"setWhiteLevel", label:'White Level' } standardTile("switch", "device.switch", width: 1, height: 1, canChangeIcon: true) { - state "on", label:'${name}', action:"switch.off", icon:"st.illuminance.illuminance.bright", backgroundColor:"#79b821", nextState:"turningOff" + state "on", label:'${name}', action:"switch.off", icon:"st.illuminance.illuminance.bright", backgroundColor:"#00A0DC", nextState:"turningOff" state "off", label:'${name}', action:"switch.on", icon:"st.illuminance.illuminance.dark", backgroundColor:"#ffffff", nextState:"turningOn" - state "turningOn", label:'${name}', icon:"st.illuminance.illuminance.bright", backgroundColor:"#79b821" + state "turningOn", label:'${name}', icon:"st.illuminance.illuminance.bright", backgroundColor:"#00A0DC" state "turningOff", label:'${name}', icon:"st.illuminance.illuminance.dark", backgroundColor:"#ffffff" } valueTile("power", "device.power", decoration: "flat") { diff --git a/devicetypes/smartthings/fortrezz-water-valve.src/.st-ignore b/devicetypes/smartthings/fortrezz-water-valve.src/.st-ignore new file mode 100644 index 0000000..f78b46e --- /dev/null +++ b/devicetypes/smartthings/fortrezz-water-valve.src/.st-ignore @@ -0,0 +1,2 @@ +.st-ignore +README.md diff --git a/devicetypes/smartthings/fortrezz-water-valve.src/README.md b/devicetypes/smartthings/fortrezz-water-valve.src/README.md new file mode 100644 index 0000000..40c31df --- /dev/null +++ b/devicetypes/smartthings/fortrezz-water-valve.src/README.md @@ -0,0 +1,39 @@ +# FortrezZ Water Valve + +Cloud Execution + +Works with: + +* [FortrezZ Water Valve](https://www.smartthings.com/works-with-smartthings/other/fortrezz-water-valve) + +## Table of contents + +* [Capabilities](#capabilities) +* [Health](#device-health) +* [Troubleshooting](#troubleshooting) + +## Capabilities + +* **Actuator** - represents that a Device has commands +* **Health Check** - indicates ability to get device health notifications +* **Valve** - allows for the control of a valve device +* **Refresh** - _refresh()_ command for status updates +* **Sensor** - detects sensor events + +## Device Health + +FortrezZ Water Valve is polled by the hub. +As of hubCore version 0.14.38 the hub sends up reports every 15 minutes regardless of whether the state changed. +Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*15 + 2)mins = 32 mins. +Not to mention after going OFFLINE when the device is plugged back in, it might take a considerable amount of time for +the device to appear as ONLINE again. This is because if this listening device does not respond to two poll requests in a row, +it is not polled for 5 minutes by the hub. This can delay up the process of being marked ONLINE by quite some time. + +* __32min__ checkInterval + +## Troubleshooting + +If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range. +Pairing needs to be tried again by placing the device closer to the hub. +Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link: +* [FortrezZ Water Valve Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/202088434-FortrezZ-Water-Valve-Shutoff) \ No newline at end of file diff --git a/devicetypes/smartthings/fortrezz-water-valve.src/fortrezz-water-valve.groovy b/devicetypes/smartthings/fortrezz-water-valve.src/fortrezz-water-valve.groovy index 538694a..77b9595 100644 --- a/devicetypes/smartthings/fortrezz-water-valve.src/fortrezz-water-valve.groovy +++ b/devicetypes/smartthings/fortrezz-water-valve.src/fortrezz-water-valve.groovy @@ -14,11 +14,13 @@ metadata { definition (name: "Fortrezz Water Valve", namespace: "smartthings", author: "SmartThings") { capability "Actuator" + capability "Health Check" capability "Valve" capability "Refresh" capability "Sensor" fingerprint deviceId: "0x1000", inClusters: "0x25,0x72,0x86,0x71,0x22,0x70" + fingerprint mfr:"0084", prod:"0213", model:"0215", deviceJoinName: "FortrezZ Water Valve" } // simulator metadata @@ -34,10 +36,10 @@ metadata { // tile definitions tiles { standardTile("contact", "device.contact", width: 2, height: 2, canChangeIcon: true) { - state "open", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#53a7c0", nextState:"closing" - state "closed", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#e86d13", nextState:"opening" - state "opening", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#ffe71e" - state "closing", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#ffe71e" + state "open", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#00A0DC", nextState:"closing" + state "closed", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#ffffff", nextState:"opening" + state "opening", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#00A0DC" + state "closing", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#ffffff" } standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") { state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh" @@ -48,6 +50,11 @@ metadata { } } +def updated(){ +// Device-Watch simply pings if no device events received for 32min(checkInterval) + sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) +} + def parse(String description) { log.trace description def result = null @@ -76,6 +83,13 @@ def close() { zwave.switchBinaryV1.switchBinarySet(switchValue: 0xFF).format() } +/** + * PING is used by Device-Watch in attempt to reach the Device + * */ +def ping() { + refresh() +} + def refresh() { zwave.switchBinaryV1.switchBinaryGet().format() } diff --git a/devicetypes/smartthings/foscam.src/foscam.groovy b/devicetypes/smartthings/foscam.src/foscam.groovy index c509e65..737ac6b 100644 --- a/devicetypes/smartthings/foscam.src/foscam.groovy +++ b/devicetypes/smartthings/foscam.src/foscam.groovy @@ -41,7 +41,7 @@ standardTile("take", "device.image", width: 1, height: 1, canChangeIcon: false, inactiveLabel: true, canChangeBackground: false) { state "take", label: "Take", action: "Image Capture.take", icon: "st.camera.dropcam", backgroundColor: "#FFFFFF", nextState:"taking" - state "taking", label:'Taking', action: "", icon: "st.camera.dropcam", backgroundColor: "#53a7c0" + state "taking", label:'Taking', action: "", icon: "st.camera.dropcam", backgroundColor: "#00A0DC" state "image", label: "Take", action: "Image Capture.take", icon: "st.camera.dropcam", backgroundColor: "#FFFFFF", nextState:"taking" } diff --git a/devicetypes/smartthings/ge-link-bulb.src/ge-link-bulb.groovy b/devicetypes/smartthings/ge-link-bulb.src/ge-link-bulb.groovy index d806b69..2510a2f 100644 --- a/devicetypes/smartthings/ge-link-bulb.src/ge-link-bulb.groovy +++ b/devicetypes/smartthings/ge-link-bulb.src/ge-link-bulb.groovy @@ -61,9 +61,9 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#00a0dc", nextState:"turningOff" attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#00a0dc", nextState:"turningOff" attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn" } tileAttribute ("device.level", key: "SLIDER_CONTROL") { @@ -99,7 +99,7 @@ def parse(String description) { def poll() { def refreshCmds = [ - "st wattr 0x${device.deviceNetworkId} 1 8 0x10 0x21 {${state?.dOnOff ?: '0000'}}", "delay 500" + "st wattr 0x${device.deviceNetworkId} 1 8 0x10 0x21 {${state?.dOnOff ?: '0000'}}", "delay 2000" ] return refreshCmds + zigbee.onOffRefresh() + zigbee.levelRefresh() @@ -197,7 +197,7 @@ def off() { def refresh() { def refreshCmds = [ - "st wattr 0x${device.deviceNetworkId} 1 8 0x10 0x21 {${state?.dOnOff ?: '0000'}}", "delay 500" + "st wattr 0x${device.deviceNetworkId} 1 8 0x10 0x21 {${state?.dOnOff ?: '0000'}}", "delay 2000" ] return refreshCmds + zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.onOffConfig() diff --git a/devicetypes/smartthings/gentle-wake-up-controller.src/gentle-wake-up-controller.groovy b/devicetypes/smartthings/gentle-wake-up-controller.src/gentle-wake-up-controller.groovy index b34a355..a142cdd 100644 --- a/devicetypes/smartthings/gentle-wake-up-controller.src/gentle-wake-up-controller.groovy +++ b/devicetypes/smartthings/gentle-wake-up-controller.src/gentle-wake-up-controller.groovy @@ -31,7 +31,7 @@ metadata { tileAttribute("sessionStatus", key: "PRIMARY_CONTROL") { attributeState "cancelled", action: "timed session.start", icon: "http://f.cl.ly/items/322n181j2K3f281r2s0A/playbutton.png", backgroundColor: "#ffffff", nextState: "running" attributeState "stopped", action: "timed session.start", icon: "http://f.cl.ly/items/322n181j2K3f281r2s0A/playbutton.png", backgroundColor: "#ffffff", nextState: "cancelled" - attributeState "running", action: "timed session.stop", icon: "http://f.cl.ly/items/0B3y3p2V3X2l3P3y3W09/stopbutton.png", backgroundColor: "#79b821", nextState: "cancelled" + attributeState "running", action: "timed session.stop", icon: "http://f.cl.ly/items/0B3y3p2V3X2l3P3y3W09/stopbutton.png", backgroundColor: "#00A0DC", nextState: "cancelled" } tileAttribute("timeRemaining", key: "SECONDARY_CONTROL") { attributeState "timeRemaining", label:'${currentValue} remaining' @@ -45,7 +45,7 @@ metadata { standardTile("sessionStatusTile", "sessionStatus", width: 1, height: 1, canChangeIcon: true) { state "cancelled", label: "Stopped", action: "timed session.start", backgroundColor: "#ffffff", icon: "http://f.cl.ly/items/1J1g0H2P0S1G1f2O1s1s/icon.png" state "stopped", label: "Stopped", action: "timed session.start", backgroundColor: "#ffffff", icon: "http://f.cl.ly/items/1J1g0H2P0S1G1f2O1s1s/icon.png" - state "running", label: "Running", action: "timed session.stop", backgroundColor: "#79b821", icon: "http://f.cl.ly/items/1J1g0H2P0S1G1f2O1s1s/icon.png" + state "running", label: "Running", action: "timed session.stop", backgroundColor: "#00A0DC", icon: "http://f.cl.ly/items/1J1g0H2P0S1G1f2O1s1s/icon.png" } // duration diff --git a/devicetypes/smartthings/harmony-activity.src/harmony-activity.groovy b/devicetypes/smartthings/harmony-activity.src/harmony-activity.groovy index e87a185..56bb6d2 100644 --- a/devicetypes/smartthings/harmony-activity.src/harmony-activity.groovy +++ b/devicetypes/smartthings/harmony-activity.src/harmony-activity.groovy @@ -32,7 +32,7 @@ metadata { tiles { standardTile("button", "device.switch", width: 2, height: 2, canChangeIcon: true) { state "off", label: 'Off', action: "switch.on", icon: "st.harmony.harmony-hub-icon", backgroundColor: "#ffffff", nextState: "on" - state "on", label: 'On', action: "switch.off", icon: "st.harmony.harmony-hub-icon", backgroundColor: "#79b821", nextState: "off" + state "on", label: 'On', action: "switch.off", icon: "st.harmony.harmony-hub-icon", backgroundColor: "#00A0DC", nextState: "off" } standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") { state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh" diff --git a/devicetypes/smartthings/homeseer-multisensor.src/homeseer-multisensor.groovy b/devicetypes/smartthings/homeseer-multisensor.src/homeseer-multisensor.groovy index 778eda8..9dd7510 100644 --- a/devicetypes/smartthings/homeseer-multisensor.src/homeseer-multisensor.groovy +++ b/devicetypes/smartthings/homeseer-multisensor.src/homeseer-multisensor.groovy @@ -39,8 +39,8 @@ metadata { tiles { standardTile("motion", "device.motion", width: 2, height: 2) { - state "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0" - state "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff" + state "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC" + state "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc" } valueTile("temperature", "device.temperature", inactiveLabel: false) { state "temperature", label:'${currentValue}°', diff --git a/devicetypes/smartthings/hue-bloom.src/hue-bloom.groovy b/devicetypes/smartthings/hue-bloom.src/hue-bloom.groovy index ae48f0d..f7a755e 100644 --- a/devicetypes/smartthings/hue-bloom.src/hue-bloom.groovy +++ b/devicetypes/smartthings/hue-bloom.src/hue-bloom.groovy @@ -17,6 +17,7 @@ metadata { capability "Refresh" capability "Sensor" capability "Health Check" + capability "Light" command "setAdjustedColor" command "reset" @@ -30,9 +31,9 @@ metadata { tiles (scale: 2){ multiAttributeTile(name:"rich-control", type: "lighting", width: 6, height: 4, canChangeIcon: true){ tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" } tileAttribute ("device.level", key: "SLIDER_CONTROL") { @@ -57,7 +58,7 @@ metadata { } void installed() { - sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}") + sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}", displayed: false) } // parse events into attributes diff --git a/devicetypes/smartthings/hue-bridge.src/hue-bridge.groovy b/devicetypes/smartthings/hue-bridge.src/hue-bridge.groovy index e7fbce1..b6e4267 100644 --- a/devicetypes/smartthings/hue-bridge.src/hue-bridge.groovy +++ b/devicetypes/smartthings/hue-bridge.src/hue-bridge.groovy @@ -7,6 +7,7 @@ metadata { // Automatically generated. Make future change here. definition (name: "Hue Bridge", namespace: "smartthings", author: "SmartThings") { + capability "Bridge" capability "Health Check" attribute "networkAddress", "string" @@ -26,7 +27,7 @@ metadata { multiAttributeTile(name:"rich-control"){ tileAttribute ("device.status", key: "PRIMARY_CONTROL") { attributeState "Offline", label: '${currentValue}', action: "", icon: "st.Lighting.light99-hue", backgroundColor: "#ffffff" - attributeState "Online", label: '${currentValue}', action: "", icon: "st.Lighting.light99-hue", backgroundColor: "#79b821" + attributeState "Online", label: '${currentValue}', action: "", icon: "st.Lighting.light99-hue", backgroundColor: "#00A0DC" } } valueTile("doNotRemove", "v", decoration: "flat", height: 2, width: 6, inactiveLabel: false) { @@ -45,7 +46,7 @@ metadata { } void installed() { - sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}") + sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}", displayed: false) } // parse events into attributes diff --git a/devicetypes/smartthings/hue-bulb.src/hue-bulb.groovy b/devicetypes/smartthings/hue-bulb.src/hue-bulb.groovy index 143b0b3..377f05b 100644 --- a/devicetypes/smartthings/hue-bulb.src/hue-bulb.groovy +++ b/devicetypes/smartthings/hue-bulb.src/hue-bulb.groovy @@ -18,6 +18,7 @@ metadata { capability "Refresh" capability "Sensor" capability "Health Check" + capability "Light" command "setAdjustedColor" command "reset" @@ -31,9 +32,9 @@ metadata { tiles (scale: 2){ multiAttributeTile(name:"rich-control", type: "lighting", width: 6, height: 4, canChangeIcon: true){ tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" } tileAttribute ("device.level", key: "SLIDER_CONTROL") { @@ -66,7 +67,7 @@ metadata { } void installed() { - sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}") + sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}", displayed: false) } // parse events into attributes diff --git a/devicetypes/smartthings/hue-lux-bulb.src/hue-lux-bulb.groovy b/devicetypes/smartthings/hue-lux-bulb.src/hue-lux-bulb.groovy index d855d38..d82ce66 100644 --- a/devicetypes/smartthings/hue-lux-bulb.src/hue-lux-bulb.groovy +++ b/devicetypes/smartthings/hue-lux-bulb.src/hue-lux-bulb.groovy @@ -14,7 +14,8 @@ metadata { capability "Switch" capability "Refresh" capability "Sensor" - capability "Health Check" + capability "Health Check" + capability "Light" command "refresh" } @@ -26,9 +27,9 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"rich-control", type: "lighting", canChangeIcon: true){ tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" } tileAttribute ("device.level", key: "SLIDER_CONTROL") { @@ -50,7 +51,7 @@ metadata { } void installed() { - sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}") + sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}", displayed: false) } // parse events into attributes diff --git a/devicetypes/smartthings/hue-white-ambiance-bulb.src/hue-white-ambiance-bulb.groovy b/devicetypes/smartthings/hue-white-ambiance-bulb.src/hue-white-ambiance-bulb.groovy index 718ed57..419fe37 100644 --- a/devicetypes/smartthings/hue-white-ambiance-bulb.src/hue-white-ambiance-bulb.groovy +++ b/devicetypes/smartthings/hue-white-ambiance-bulb.src/hue-white-ambiance-bulb.groovy @@ -16,6 +16,7 @@ metadata { capability "Switch" capability "Refresh" capability "Health Check" + capability "Light" command "refresh" } @@ -27,9 +28,9 @@ metadata { tiles (scale: 2){ multiAttributeTile(name:"rich-control", type: "lighting", width: 6, height: 4, canChangeIcon: true){ tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" } tileAttribute ("device.level", key: "SLIDER_CONTROL") { @@ -55,7 +56,7 @@ metadata { } void installed() { - sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}") + sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}", displayed: false) } // parse events into attributes diff --git a/devicetypes/smartthings/life360-user.src/life360-user.groovy b/devicetypes/smartthings/life360-user.src/life360-user.groovy index 5b72c64..c4c2b6f 100644 --- a/devicetypes/smartthings/life360-user.src/life360-user.groovy +++ b/devicetypes/smartthings/life360-user.src/life360-user.groovy @@ -29,7 +29,7 @@ metadata { tiles { standardTile("presence", "device.presence", width: 2, height: 2, canChangeBackground: true) { - state("present", labelIcon:"st.presence.tile.mobile-present", backgroundColor:"#53a7c0") + state("present", labelIcon:"st.presence.tile.mobile-present", backgroundColor:"#00A0DC") state("not present", labelIcon:"st.presence.tile.mobile-not-present", backgroundColor:"#ffffff") } diff --git a/devicetypes/smartthings/lifx-color-bulb.src/lifx-color-bulb.groovy b/devicetypes/smartthings/lifx-color-bulb.src/lifx-color-bulb.groovy index 5ecfae0..964f8bf 100644 --- a/devicetypes/smartthings/lifx-color-bulb.src/lifx-color-bulb.groovy +++ b/devicetypes/smartthings/lifx-color-bulb.src/lifx-color-bulb.groovy @@ -14,6 +14,7 @@ metadata { capability "Refresh" capability "Sensor" capability "Health Check" + capability "Light" } simulator { @@ -23,9 +24,9 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"http://hosted.lifx.co/smartthings/v1/196xOn.png", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "on", label:'${name}', action:"switch.off", icon:"http://hosted.lifx.co/smartthings/v1/196xOn.png", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "off", label:'${name}', action:"switch.on", icon:"http://hosted.lifx.co/smartthings/v1/196xOff.png", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'Turning on', action:"switch.off", icon:"http://hosted.lifx.co/smartthings/v1/196xOn.png", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "turningOn", label:'Turning on', action:"switch.off", icon:"http://hosted.lifx.co/smartthings/v1/196xOn.png", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "turningOff", label:'Turning off', action:"switch.on", icon:"http://hosted.lifx.co/smartthings/v1/196xOff.png", backgroundColor:"#ffffff", nextState:"turningOn" } diff --git a/devicetypes/smartthings/lifx-white-bulb.src/lifx-white-bulb.groovy b/devicetypes/smartthings/lifx-white-bulb.src/lifx-white-bulb.groovy index 16e7c57..472f269 100644 --- a/devicetypes/smartthings/lifx-white-bulb.src/lifx-white-bulb.groovy +++ b/devicetypes/smartthings/lifx-white-bulb.src/lifx-white-bulb.groovy @@ -13,6 +13,7 @@ metadata { capability "Refresh" capability "Sensor" capability "Health Check" + capability "Light" } simulator { @@ -22,9 +23,9 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"http://hosted.lifx.co/smartthings/v1/196xOn.png", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "on", label:'${name}', action:"switch.off", icon:"http://hosted.lifx.co/smartthings/v1/196xOn.png", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "off", label:'${name}', action:"switch.on", icon:"http://hosted.lifx.co/smartthings/v1/196xOff.png", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'Turning on', action:"switch.off", icon:"http://hosted.lifx.co/smartthings/v1/196xOn.png", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "turningOn", label:'Turning on', action:"switch.off", icon:"http://hosted.lifx.co/smartthings/v1/196xOn.png", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "turningOff", label:'Turning off', action:"switch.on", icon:"http://hosted.lifx.co/smartthings/v1/196xOff.png", backgroundColor:"#ffffff", nextState:"turningOn" } diff --git a/devicetypes/smartthings/mimolite-garage-door-controller.src/mimolite-garage-door-controller.groovy b/devicetypes/smartthings/mimolite-garage-door-controller.src/mimolite-garage-door-controller.groovy index fb7407e..9440d21 100644 --- a/devicetypes/smartthings/mimolite-garage-door-controller.src/mimolite-garage-door-controller.groovy +++ b/devicetypes/smartthings/mimolite-garage-door-controller.src/mimolite-garage-door-controller.groovy @@ -36,6 +36,7 @@ metadata { capability "Switch" capability "Refresh" capability "Contact Sensor" + capability "Light" attribute "powered", "string" @@ -53,11 +54,11 @@ metadata { // UI tile definitions tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { - state "doorClosed", label: "Closed", action: "on", icon: "st.doors.garage.garage-closed", backgroundColor: "#79b821" - state "doorOpen", label: "Open", action: "on", icon: "st.doors.garage.garage-open", backgroundColor: "#ffa81e" - state "doorOpening", label: "Opening", action: "on", icon: "st.doors.garage.garage-opening", backgroundColor: "#ffa81e" - state "doorClosing", label: "Closing", action: "on", icon: "st.doors.garage.garage-closing", backgroundColor: "#ffa81e" - state "on", label: "Actuate", action: "off", icon: "st.doors.garage.garage-closed", backgroundColor: "#53a7c0" + state "doorClosed", label: "Closed", action: "on", icon: "st.doors.garage.garage-closed", backgroundColor: "#00A0DC" + state "doorOpen", label: "Open", action: "on", icon: "st.doors.garage.garage-open", backgroundColor: "#e86d13" + state "doorOpening", label: "Opening", action: "on", icon: "st.doors.garage.garage-opening", backgroundColor: "#e86d13" + state "doorClosing", label: "Closing", action: "on", icon: "st.doors.garage.garage-closing", backgroundColor: "#00A0DC" + state "on", label: "Actuate", action: "off", icon: "st.doors.garage.garage-closed", backgroundColor: "#00A0DC" state "off", label: '${name}', action: "on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" } standardTile("contact", "device.contact", inactiveLabel: false) { diff --git a/devicetypes/smartthings/mobile-presence.src/mobile-presence.groovy b/devicetypes/smartthings/mobile-presence.src/mobile-presence.groovy index 8ed14ab..7af7519 100644 --- a/devicetypes/smartthings/mobile-presence.src/mobile-presence.groovy +++ b/devicetypes/smartthings/mobile-presence.src/mobile-presence.groovy @@ -27,8 +27,8 @@ metadata { tiles { standardTile("presence", "device.presence", width: 2, height: 2, canChangeBackground: true) { - state("present", labelIcon:"st.presence.tile.mobile-present", backgroundColor:"#53a7c0") - state("not present", labelIcon:"st.presence.tile.mobile-not-present", backgroundColor:"#ebeef2") + state("present", labelIcon:"st.presence.tile.mobile-present", backgroundColor:"#00A0DC") + state("not present", labelIcon:"st.presence.tile.mobile-not-present", backgroundColor:"#ffffff") } main "presence" details "presence" diff --git a/devicetypes/smartthings/momentary-button-tile.src/momentary-button-tile.groovy b/devicetypes/smartthings/momentary-button-tile.src/momentary-button-tile.groovy index 7a164fa..923836e 100644 --- a/devicetypes/smartthings/momentary-button-tile.src/momentary-button-tile.groovy +++ b/devicetypes/smartthings/momentary-button-tile.src/momentary-button-tile.groovy @@ -32,7 +32,7 @@ metadata { tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { state "off", label: 'Push', action: "momentary.push", backgroundColor: "#ffffff", nextState: "on" - state "on", label: 'Push', action: "momentary.push", backgroundColor: "#53a7c0" + state "on", label: 'Push', action: "momentary.push", backgroundColor: "#00A0DC" } main "switch" details "switch" diff --git a/devicetypes/smartthings/motion-detector.src/motion-detector.groovy b/devicetypes/smartthings/motion-detector.src/motion-detector.groovy index a7c86a4..ca1de53 100644 --- a/devicetypes/smartthings/motion-detector.src/motion-detector.groovy +++ b/devicetypes/smartthings/motion-detector.src/motion-detector.groovy @@ -28,8 +28,8 @@ metadata { // UI tile definitions tiles { standardTile("motion", "device.motion", width: 2, height: 2) { - state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0") - state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff") + state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC") + state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc") } main "motion" diff --git a/devicetypes/smartthings/nyce-motion-sensor.src/nyce-motion-sensor.groovy b/devicetypes/smartthings/nyce-motion-sensor.src/nyce-motion-sensor.groovy index f48e788..209c7fa 100644 --- a/devicetypes/smartthings/nyce-motion-sensor.src/nyce-motion-sensor.groovy +++ b/devicetypes/smartthings/nyce-motion-sensor.src/nyce-motion-sensor.groovy @@ -21,6 +21,7 @@ metadata { capability "Configuration" capability "Battery" capability "Refresh" + capability "Sensor" command "enrollResponse" @@ -31,8 +32,8 @@ metadata { tiles { standardTile("motion", "device.motion", width: 2, height: 2) { - state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0") - state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff") + state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC") + state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc") } valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false) { diff --git a/devicetypes/smartthings/nyce-open-closed-sensor.src/nyce-open-closed-sensor.groovy b/devicetypes/smartthings/nyce-open-closed-sensor.src/nyce-open-closed-sensor.groovy index 7f75068..70e414d 100644 --- a/devicetypes/smartthings/nyce-open-closed-sensor.src/nyce-open-closed-sensor.groovy +++ b/devicetypes/smartthings/nyce-open-closed-sensor.src/nyce-open-closed-sensor.groovy @@ -24,6 +24,7 @@ metadata { capability "Contact Sensor" capability "Refresh" capability "Health Check" + capability "Sensor" command "enrollResponse" @@ -41,8 +42,8 @@ metadata { 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") + state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#e86d13") + state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#00a0dc") } valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false) { diff --git a/devicetypes/smartthings/on-off-button-tile.src/on-off-button-tile.groovy b/devicetypes/smartthings/on-off-button-tile.src/on-off-button-tile.groovy index 59b82bf..ec86e5a 100644 --- a/devicetypes/smartthings/on-off-button-tile.src/on-off-button-tile.groovy +++ b/devicetypes/smartthings/on-off-button-tile.src/on-off-button-tile.groovy @@ -31,7 +31,7 @@ metadata { tiles { standardTile("button", "device.switch", width: 2, height: 2, canChangeIcon: true) { state "off", label: 'Off', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "on" - state "on", label: 'On', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821", nextState: "off" + state "on", label: 'On', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC", nextState: "off" } main "button" details "button" diff --git a/devicetypes/smartthings/on-off-shield.src/on-off-shield.groovy b/devicetypes/smartthings/on-off-shield.src/on-off-shield.groovy index 5286a25..1007c3d 100644 --- a/devicetypes/smartthings/on-off-shield.src/on-off-shield.groovy +++ b/devicetypes/smartthings/on-off-shield.src/on-off-shield.groovy @@ -31,7 +31,7 @@ metadata { // UI tile definitions tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true, canChangeBackground: true) { - state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" + state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC" state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" } diff --git a/devicetypes/smartthings/open-closed-sensor.src/open-closed-sensor.groovy b/devicetypes/smartthings/open-closed-sensor.src/open-closed-sensor.groovy index d05a565..8883096 100644 --- a/devicetypes/smartthings/open-closed-sensor.src/open-closed-sensor.groovy +++ b/devicetypes/smartthings/open-closed-sensor.src/open-closed-sensor.groovy @@ -29,8 +29,8 @@ metadata { // UI tile definitions 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" + state "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#e86d13" + state "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#00A0DC" } main "contact" @@ -40,14 +40,11 @@ metadata { // Parse incoming device messages to generate events def parse(String description) { - def name = null - def value = description - if (zigbee.isZoneType19(description)) { - name = "contact" - value = zigbee.translateStatusZoneType19(description) ? "open" : "closed" + def resMap + if (description.startsWith("zone")) { + resMap = createEvent(name: "contact", value: zigbee.parseZoneStatus(description).isAlarm1Set() ? "open" : "closed") } - def result = createEvent(name: name, value: value) - log.debug "Parse returned ${result?.descriptionText}" - return result + log.debug "Parse returned $resMap" + return resMap } diff --git a/devicetypes/smartthings/rgbw-light.src/rgbw-light.groovy b/devicetypes/smartthings/rgbw-light.src/rgbw-light.groovy index fd729a3..f4c3c81 100644 --- a/devicetypes/smartthings/rgbw-light.src/rgbw-light.groovy +++ b/devicetypes/smartthings/rgbw-light.src/rgbw-light.groovy @@ -37,9 +37,9 @@ metadata { } standardTile("switch", "device.switch", width: 1, height: 1, canChangeIcon: true) { - state "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + state "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00a0dc", nextState:"turningOff" state "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - state "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + state "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00a0dc", nextState:"turningOff" state "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" } standardTile("reset", "device.reset", inactiveLabel: false, decoration: "flat") { diff --git a/devicetypes/smartthings/secure-dimmer.src/secure-dimmer.groovy b/devicetypes/smartthings/secure-dimmer.src/secure-dimmer.groovy index 82af5e4..5c0f599 100644 --- a/devicetypes/smartthings/secure-dimmer.src/secure-dimmer.groovy +++ b/devicetypes/smartthings/secure-dimmer.src/secure-dimmer.groovy @@ -42,9 +42,9 @@ metadata { tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { - state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" + state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff" state "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" - state "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" + state "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff" state "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" } controlTile("levelSliderControl", "device.level", "slider", height: 1, width: 3, inactiveLabel: false) { diff --git a/devicetypes/smartthings/smartpower-dimming-outlet.src/smartpower-dimming-outlet.groovy b/devicetypes/smartthings/smartpower-dimming-outlet.src/smartpower-dimming-outlet.groovy index 9539376..fea3c37 100644 --- a/devicetypes/smartthings/smartpower-dimming-outlet.src/smartpower-dimming-outlet.groovy +++ b/devicetypes/smartthings/smartpower-dimming-outlet.src/smartpower-dimming-outlet.groovy @@ -24,6 +24,7 @@ metadata { capability "Refresh" capability "Actuator" capability "Sensor" + capability "Outlet" fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0B04,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "4257050-ZHAC" @@ -69,288 +70,36 @@ metadata { def parse(String description) { log.debug "description is $description" - def event = [:] - def finalResult = isKnownDescription(description) - if (finalResult) { - log.info finalResult - if (finalResult.type == "update") { - log.info "$device updates: ${finalResult.value}" - event = null - } - else if (finalResult.type == "power") { - def powerValue = (finalResult.value as Integer)/10 - event = createEvent(name: "power", value: powerValue) - - /* - Dividing by 10 as the Divisor is 10000 and unit is kW for the device. AttrId: 0302 and 0300. Simplifying to 10 - - power level is an integer. The exact power level with correct units needs to be handled in the device type - to account for the different Divisor value (AttrId: 0302) and POWER Unit (AttrId: 0300). CLUSTER for simple metering is 0702 - */ - } - else { - event = createEvent(name: finalResult.type, value: finalResult.value) - } - } - else { + def event = zigbee.getEvent(description) + if (!event) { log.warn "DID NOT PARSE MESSAGE for description : $description" - log.debug parseDescriptionAsMap(description) + log.debug zigbee.parseDescriptionAsMap(description) + } else if (event.name == "power") { + /* + Dividing by 10 as the Divisor is 10000 and unit is kW for the device. Simplifying to 10 power level is an integer. + */ + event.value = event.value / 10 } - return event -} -// Commands to device -def zigbeeCommand(cluster, attribute){ - "st cmd 0x${device.deviceNetworkId} ${endpointId} ${cluster} ${attribute} {}" -} - -def off() { - zigbeeCommand("6", "0") -} - -def on() { - zigbeeCommand("6", "1") + return event ? createEvent(event) : event } def setLevel(value) { - value = value as Integer - if (value == 0) { - off() - } - else { - if (device.latestValue("switch") == "off") { - sendEvent(name: "switch", value: "on") - } - sendEvent(name: "level", value: value) - setLevelWithRate(value, "0000") //value is between 0 to 100 - } + zigbee.setLevel(value) +} + +def off() { + zigbee.off() +} + +def on() { + zigbee.on() } def refresh() { - [ - "st rattr 0x${device.deviceNetworkId} ${endpointId} 6 0", "delay 500", - "st rattr 0x${device.deviceNetworkId} ${endpointId} 8 0", "delay 500", - "st rattr 0x${device.deviceNetworkId} ${endpointId} 0x0B04 0x050B", "delay 500" - ] - + zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.electricMeasurementPowerRefresh() } def configure() { - refresh() + onOffConfig() + levelConfig() + powerConfig() -} - - -private getEndpointId() { - new BigInteger(device.endpointId, 16).toString() -} - -private hex(value, width=2) { - def s = new BigInteger(Math.round(value).toString()).toString(16) - while (s.size() < width) { - s = "0" + s - } - s -} - -private String swapEndianHex(String hex) { - reverseArray(hex.decodeHex()).encodeHex() -} - -private Integer convertHexToInt(hex) { - Integer.parseInt(hex,16) -} - -//Need to reverse array of size 2 -private byte[] reverseArray(byte[] array) { - byte tmp; - tmp = array[1]; - array[1] = array[0]; - array[0] = tmp; - return array -} - -def parseDescriptionAsMap(description) { - if (description?.startsWith("read attr -")) { - (description - "read attr - ").split(",").inject([:]) { map, param -> - def nameAndValue = param.split(":") - map += [(nameAndValue[0].trim()): nameAndValue[1].trim()] - } - } - else if (description?.startsWith("catchall: ")) { - def seg = (description - "catchall: ").split(" ") - def zigbeeMap = [:] - zigbeeMap += [raw: (description - "catchall: ")] - zigbeeMap += [profileId: seg[0]] - zigbeeMap += [clusterId: seg[1]] - zigbeeMap += [sourceEndpoint: seg[2]] - zigbeeMap += [destinationEndpoint: seg[3]] - zigbeeMap += [options: seg[4]] - zigbeeMap += [messageType: seg[5]] - zigbeeMap += [dni: seg[6]] - zigbeeMap += [isClusterSpecific: Short.valueOf(seg[7], 16) != 0] - zigbeeMap += [isManufacturerSpecific: Short.valueOf(seg[8], 16) != 0] - zigbeeMap += [manufacturerId: seg[9]] - zigbeeMap += [command: seg[10]] - zigbeeMap += [direction: seg[11]] - zigbeeMap += [data: seg.size() > 12 ? seg[12].split("").findAll { it }.collate(2).collect { - it.join('') - } : []] - - zigbeeMap - } -} - -def isKnownDescription(description) { - if ((description?.startsWith("catchall:")) || (description?.startsWith("read attr -"))) { - def descMap = parseDescriptionAsMap(description) - if (descMap.cluster == "0006" || descMap.clusterId == "0006") { - isDescriptionOnOff(descMap) - } - else if (descMap.cluster == "0008" || descMap.clusterId == "0008"){ - isDescriptionLevel(descMap) - } - else if (descMap.cluster == "0B04" || descMap.clusterId == "0B04"){ - isDescriptionPower(descMap) - } - else { - return [:] - } - } - else if(description?.startsWith("on/off:")) { - def switchValue = description?.endsWith("1") ? "on" : "off" - return [type: "switch", value : switchValue] - } - else { - return [:] - } -} - -def isDescriptionOnOff(descMap) { - def switchValue = "undefined" - if (descMap.cluster == "0006") { //cluster info from read attr - value = descMap.value - if (value == "01"){ - switchValue = "on" - } - else if (value == "00"){ - switchValue = "off" - } - } - else if (descMap.clusterId == "0006") { - //cluster info from catch all - //command 0B is Default response and the last two bytes are [on/off][success]. on/off=00, success=00 - //command 01 is Read attr response. the last two bytes are [datatype][value]. boolean datatype=10; on/off value = 01/00 - if ((descMap.command=="0B" && descMap.raw.endsWith("0100")) || (descMap.command=="01" && descMap.raw.endsWith("1001"))){ - switchValue = "on" - } - else if ((descMap.command=="0B" && descMap.raw.endsWith("0000")) || (descMap.command=="01" && descMap.raw.endsWith("1000"))){ - switchValue = "off" - } - else if(descMap.command=="07"){ - return [type: "update", value : "switch (0006) capability configured successfully"] - } - } - - if (switchValue != "undefined"){ - return [type: "switch", value : switchValue] - } - else { - return [:] - } - -} - -//@return - false or "success" or level [0-100] -def isDescriptionLevel(descMap) { - def dimmerValue = -1 - if (descMap.cluster == "0008"){ - //TODO: the message returned with catchall is command 0B with clusterId 0008. That is just a confirmation message - def value = convertHexToInt(descMap.value) - dimmerValue = Math.round(value * 100 / 255) - if(dimmerValue==0 && value > 0) { - dimmerValue = 1 //handling for non-zero hex value less than 3 - } - } - else if(descMap.clusterId == "0008") { - if(descMap.command=="0B"){ - return [type: "update", value : "level updated successfully"] //device updating the level change was successful. no value sent. - } - else if(descMap.command=="07"){ - return [type: "update", value : "level (0008) capability configured successfully"] - } - } - - if (dimmerValue != -1){ - return [type: "level", value : dimmerValue] - } - else { - return [:] - } -} - -def isDescriptionPower(descMap) { - def powerValue = "undefined" - if (descMap.cluster == "0B04") { - if (descMap.attrId == "050b") { - if(descMap.value!="ffff") - powerValue = convertHexToInt(descMap.value) - } - } - else if (descMap.clusterId == "0B04") { - if(descMap.command=="07"){ - return [type: "update", value : "power (0B04) capability configured successfully"] - } - } - - if (powerValue != "undefined"){ - return [type: "power", value : powerValue] - } - else { - return [:] - } -} - - -def onOffConfig() { - [ - "zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 6 {${device.zigbeeId}} {}", "delay 200", - "zcl global send-me-a-report 6 0 0x10 0 600 {01}", - "send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 1500" - ] -} - -//level config for devices with min reporting interval as 5 seconds and reporting interval if no activity as 1hour (3600s) -//min level change is 01 -def levelConfig() { - [ - "zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 8 {${device.zigbeeId}} {}", "delay 200", - "zcl global send-me-a-report 8 0 0x20 5 3600 {01}", - "send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 1500" - ] -} - -//power config for devices with min reporting interval as 1 seconds and reporting interval if no activity as 10min (600s) -//min change in value is 05 -def powerConfig() { - [ - "zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 0x0B04 {${device.zigbeeId}} {}", "delay 200", - "zcl global send-me-a-report 0x0B04 0x050B 0x29 1 600 {05 00}", //The send-me-a-report is custom to the attribute type for CentraLite - "send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500" - ] -} - -def setLevelWithRate(level, rate) { - if(rate == null){ - rate = "0000" - } - level = convertToHexString(level * 255 / 100) //Converting the 0-100 range to 0-FF range in hex - "st cmd 0x${device.deviceNetworkId} ${endpointId} 8 4 {$level $rate}" -} - -String convertToHexString(value, width=2) { - def s = new BigInteger(Math.round(value).toString()).toString(16) - while (s.size() < width) { - s = "0" + s - } - s + refresh() + zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.electricMeasurementPowerConfig() } diff --git a/devicetypes/smartthings/smartpower-outlet-v1.src/smartpower-outlet-v1.groovy b/devicetypes/smartthings/smartpower-outlet-v1.src/smartpower-outlet-v1.groovy index a65c5bc..7305731 100644 --- a/devicetypes/smartthings/smartpower-outlet-v1.src/smartpower-outlet-v1.groovy +++ b/devicetypes/smartthings/smartpower-outlet-v1.src/smartpower-outlet-v1.groovy @@ -4,6 +4,7 @@ metadata { capability "Actuator" capability "Switch" capability "Sensor" + capability "Outlet" fingerprint profileId: "0104", inClusters: "0006, 0004, 0003, 0000, 0005", outClusters: "0019", manufacturer: "Compacta International, Ltd", model: "ZBMPlug15", deviceJoinName: "SmartPower Outlet V1" } @@ -23,7 +24,7 @@ metadata { multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { attributeState "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" - attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" + attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC" } } main "switch" @@ -51,7 +52,7 @@ def on() { 'zcl on-off on', 'delay 200', "send 0x${zigbee.deviceNetworkId} 0x01 0x${zigbee.endpointId}", - 'delay 500' + 'delay 2000' ] @@ -62,6 +63,6 @@ def off() { 'zcl on-off off', 'delay 200', "send 0x${zigbee.deviceNetworkId} 0x01 0x${zigbee.endpointId}", - 'delay 500' + 'delay 2000' ] } diff --git a/devicetypes/smartthings/smartpower-outlet.src/smartpower-outlet.groovy b/devicetypes/smartthings/smartpower-outlet.src/smartpower-outlet.groovy index 03e475c..76e0dc7 100644 --- a/devicetypes/smartthings/smartpower-outlet.src/smartpower-outlet.groovy +++ b/devicetypes/smartthings/smartpower-outlet.src/smartpower-outlet.groovy @@ -13,10 +13,9 @@ * License for the specific language governing permissions and limitations * under the License. */ - metadata { // Automatically generated. Make future change here. - definition (name: "SmartPower Outlet", namespace: "smartthings", author: "SmartThings") { + definition(name: "SmartPower Outlet", namespace: "smartthings", author: "SmartThings") { capability "Actuator" capability "Switch" capability "Power Meter" @@ -24,10 +23,12 @@ metadata { capability "Refresh" capability "Sensor" capability "Health Check" + capability "Light" + capability "Outlet" - fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0B04,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3200", deviceJoinName: "Outlet" - fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0B04,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3200-Sgb", deviceJoinName: "Outlet" - fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0B04,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "4257050-RZHAC", deviceJoinName: "Outlet" + fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0B04,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3200", deviceJoinName: "Outlet" + fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0B04,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3200-Sgb", deviceJoinName: "Outlet" + fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0B04,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "4257050-RZHAC", deviceJoinName: "Outlet" fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0B04,0B05", outClusters: "0019" } @@ -45,32 +46,32 @@ metadata { preferences { section { image(name: 'educationalcontent', multiple: true, images: [ - "http://cdn.device-gse.smartthings.com/Outlet/US/OutletUS1.jpg", - "http://cdn.device-gse.smartthings.com/Outlet/US/OutletUS2.jpg" - ]) + "http://cdn.device-gse.smartthings.com/Outlet/US/OutletUS1.jpg", + "http://cdn.device-gse.smartthings.com/Outlet/US/OutletUS2.jpg" + ]) } } // UI tile definitions tiles(scale: 2) { - multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ - tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label: 'On', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821", nextState: "turningOff" + multiAttributeTile(name: "switch", type: "lighting", width: 6, height: 4, canChangeIcon: true) { + tileAttribute("device.switch", key: "PRIMARY_CONTROL") { + attributeState "on", label: 'On', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC", nextState: "turningOff" attributeState "off", label: 'Off', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "turningOn" - attributeState "turningOn", label: 'Turning On', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821", nextState: "turningOff" + attributeState "turningOn", label: 'Turning On', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC", nextState: "turningOff" attributeState "turningOff", label: 'Turning Off', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "turningOn" } - tileAttribute ("power", key: "SECONDARY_CONTROL") { - attributeState "power", label:'${currentValue} W' + tileAttribute("power", key: "SECONDARY_CONTROL") { + attributeState "power", label: '${currentValue} W' } } standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { - state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh" + state "default", label: '', action: "refresh.refresh", icon: "st.secondary.refresh" } main "switch" - details(["switch","refresh"]) + details(["switch", "refresh"]) } } @@ -78,52 +79,33 @@ metadata { def parse(String description) { log.debug "description is $description" - def finalResult = zigbee.getKnownDescription(description) - def event = [:] + def event = zigbee.getEvent(description) - //TODO: Remove this after getKnownDescription can parse it automatically - if (!finalResult && description!="updated") - finalResult = getPowerDescription(zigbee.parseDescriptionAsMap(description)) - - if (finalResult) { - log.info "final result = $finalResult" - if (finalResult.type == "update") { - log.info "$device updates: ${finalResult.value}" - event = null + if (event) { + if (event.name == "power") { + def value = (event.value as Integer) / 10 + event = createEvent(name: event.name, value: value, descriptionText: '{{ device.displayName }} power is {{ value }} Watts', translatable: true) + } else if (event.name == "switch") { + def descriptionText = event.value == "on" ? '{{ device.displayName }} is On' : '{{ device.displayName }} is Off' + event = createEvent(name: event.name, value: event.value, descriptionText: descriptionText, translatable: true) } - else if (finalResult.type == "power") { - def powerValue = (finalResult.value as Integer)/10 - event = createEvent(name: "power", value: powerValue, descriptionText: '{{ device.displayName }} power is {{ value }} Watts', translatable: true) - /* - Dividing by 10 as the Divisor is 10000 and unit is kW for the device. AttrId: 0302 and 0300. Simplifying to 10 - power level is an integer. The exact power level with correct units needs to be handled in the device type - to account for the different Divisor value (AttrId: 0302) and POWER Unit (AttrId: 0300). CLUSTER for simple metering is 0702 - */ - } - else { - def descriptionText = finalResult.value == "on" ? '{{ device.displayName }} is On' : '{{ device.displayName }} is Off' - event = createEvent(name: finalResult.type, value: finalResult.value, descriptionText: descriptionText, translatable: true) - } - } - else { + } else { def cluster = zigbee.parse(description) - if (cluster && cluster.clusterId == 0x0006 && cluster.command == 0x07){ + if (cluster && cluster.clusterId == 0x0006 && cluster.command == 0x07) { if (cluster.data[0] == 0x00) { log.debug "ON/OFF REPORTING CONFIG RESPONSE: " + cluster event = createEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) - } - else { + } else { log.warn "ON/OFF REPORTING CONFIG FAILED- error code:${cluster.data[0]}" event = null } - } - else { + } else { log.warn "DID NOT PARSE MESSAGE for description : $description" log.debug "${cluster}" } } - return event + return event ? createEvent(event) : event } def off() { @@ -150,42 +132,6 @@ def configure() { sendEvent(name: "checkInterval", value: 2 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) // OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity - refresh() + zigbee.onOffConfig(0, 300) + powerConfig() + refresh() + zigbee.onOffConfig(0, 300) + zigbee.electricMeasurementPowerConfig() } -//power config for devices with min reporting interval as 1 seconds and reporting interval if no activity as 10min (600s) -//min change in value is 01 -def powerConfig() { - [ - "zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 0x0B04 {${device.zigbeeId}} {}", "delay 200", - "zcl global send-me-a-report 0x0B04 0x050B 0x29 1 600 {05 00}", //The send-me-a-report is custom to the attribute type for CentraLite - "send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500" - ] -} - -private getEndpointId() { - new BigInteger(device.endpointId, 16).toString() -} - -//TODO: Remove this after getKnownDescription can parse it automatically -def getPowerDescription(descMap) { - def powerValue = "undefined" - if (descMap.cluster == "0B04") { - if (descMap.attrId == "050b") { - if(descMap.value!="ffff") - powerValue = zigbee.convertHexToInt(descMap.value) - } - } - else if (descMap.clusterId == "0B04") { - if(descMap.command=="07"){ - return [type: "update", value : "power (0B04) capability configured successfully"] - } - } - - if (powerValue != "undefined"){ - return [type: "power", value : powerValue] - } - else { - return [:] - } -} diff --git a/devicetypes/smartthings/smartsense-garage-door-multi.src/smartsense-garage-door-multi.groovy b/devicetypes/smartthings/smartsense-garage-door-multi.src/smartsense-garage-door-multi.groovy index 8454b9c..435cb2a 100644 --- a/devicetypes/smartthings/smartsense-garage-door-multi.src/smartsense-garage-door-multi.groovy +++ b/devicetypes/smartthings/smartsense-garage-door-multi.src/smartsense-garage-door-multi.groovy @@ -50,18 +50,18 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"status", type: "generic", width: 6, height: 4){ tileAttribute ("device.status", key: "PRIMARY_CONTROL") { - attributeState "closed", label:'${name}', icon:"st.doors.garage.garage-closed", backgroundColor:"#79b821", nextState:"opening" - attributeState "open", label:'${name}', icon:"st.doors.garage.garage-open", backgroundColor:"#ffa81e", nextState:"closing" - attributeState "opening", label:'${name}', icon:"st.doors.garage.garage-opening", backgroundColor:"#ffe71e" - attributeState "closing", label:'${name}', icon:"st.doors.garage.garage-closing", backgroundColor:"#ffe71e" + attributeState "closed", label:'${name}', icon:"st.doors.garage.garage-closed", backgroundColor:"#00A0DC", nextState:"opening" + attributeState "open", label:'${name}', icon:"st.doors.garage.garage-open", backgroundColor:"#e86d13", nextState:"closing" + attributeState "opening", label:'${name}', icon:"st.doors.garage.garage-opening", backgroundColor:"#e86d13" + attributeState "closing", label:'${name}', icon:"st.doors.garage.garage-closing", backgroundColor:"#00A0DC" } } 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") + state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#e86d13") + state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#00A0DC") } standardTile("acceleration", "device.acceleration", decoration: "flat", width: 2, height: 2) { - state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#53a7c0") + state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#00A0DC") state("inactive", label:'${name}', icon:"st.motion.acceleration.inactive", backgroundColor:"#ffffff") } valueTile("temperature", "device.temperature", decoration: "flat", width: 2, height: 2) { @@ -88,7 +88,7 @@ def parse(String description) { log.debug "parse($description)" def results = [:] - if (!isSupportedDescription(description) || zigbee.isZoneType19(description)) { + if (!isSupportedDescription(description) || description.startsWith("zone")) { // Ignore this in favor of orientation-based state // results = parseSingleMessage(description) } diff --git a/devicetypes/smartthings/smartsense-garage-door-sensor-button.src/smartsense-garage-door-sensor-button.groovy b/devicetypes/smartthings/smartsense-garage-door-sensor-button.src/smartsense-garage-door-sensor-button.groovy index f3ae158..1ff5426 100644 --- a/devicetypes/smartthings/smartsense-garage-door-sensor-button.src/smartsense-garage-door-sensor-button.groovy +++ b/devicetypes/smartthings/smartsense-garage-door-sensor-button.src/smartsense-garage-door-sensor-button.groovy @@ -50,17 +50,17 @@ metadata { tiles { standardTile("status", "device.status", width: 2, height: 2) { - state("closed", label:'${name}', icon:"st.doors.garage.garage-closed", action: "actuate", backgroundColor:"#79b821", nextState:"opening") - state("open", label:'${name}', icon:"st.doors.garage.garage-open", action: "actuate", backgroundColor:"#ffa81e", nextState:"closing") - state("opening", label:'${name}', icon:"st.doors.garage.garage-opening", backgroundColor:"#ffe71e") - state("closing", label:'${name}', icon:"st.doors.garage.garage-closing", backgroundColor:"#ffe71e") + state("closed", label:'${name}', icon:"st.doors.garage.garage-closed", action: "actuate", backgroundColor:"#00A0DC", nextState:"opening") + state("open", label:'${name}', icon:"st.doors.garage.garage-open", action: "actuate", backgroundColor:"#e86d13", nextState:"closing") + state("opening", label:'${name}', icon:"st.doors.garage.garage-opening", backgroundColor:"#e86d13") + state("closing", label:'${name}', icon:"st.doors.garage.garage-closing", backgroundColor:"#00A0DC") } standardTile("contact", "device.contact") { state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e") state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821") } standardTile("acceleration", "device.acceleration", decoration: "flat") { - state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#53a7c0") + state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#00A0DC") state("inactive", label:'${name}', icon:"st.motion.acceleration.inactive", backgroundColor:"#ffffff") } valueTile("temperature", "device.temperature", decoration: "flat") { @@ -117,7 +117,7 @@ def parse(String description) { log.debug "parse($description)" def results = null - if (!isSupportedDescription(description) || zigbee.isZoneType19(description)) { + if (!isSupportedDescription(description) || description.startsWith("zone")) { // Ignore this in favor of orientation-based state // results = parseSingleMessage(description) } diff --git a/devicetypes/smartthings/smartsense-moisture-sensor.src/smartsense-moisture-sensor.groovy b/devicetypes/smartthings/smartsense-moisture-sensor.src/smartsense-moisture-sensor.groovy index a8cb9d5..1e0c505 100644 --- a/devicetypes/smartthings/smartsense-moisture-sensor.src/smartsense-moisture-sensor.groovy +++ b/devicetypes/smartthings/smartsense-moisture-sensor.src/smartsense-moisture-sensor.groovy @@ -17,7 +17,7 @@ import physicalgraph.zigbee.clusters.iaszone.ZoneStatus metadata { - definition (name: "SmartSense Moisture Sensor",namespace: "smartthings", author: "SmartThings") { + definition(name: "SmartSense Moisture Sensor", namespace: "smartthings", author: "SmartThings") { capability "Configuration" capability "Battery" capability "Refresh" @@ -29,9 +29,11 @@ metadata { command "enrollResponse" - fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315-S", deviceJoinName: "Water Leak Sensor" - fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315" - fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315-Seu", deviceJoinName: "Water Leak Sensor" + fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315-S", deviceJoinName: "Water Leak Sensor" + fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315" + fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315-Seu", deviceJoinName: "Water Leak Sensor" + fingerprint inClusters: "0000,0001,0003,0020,0402,0500,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315-L", deviceJoinName: "Iris Smart Water Sensor" + fingerprint inClusters: "0000,0001,0003,0020,0402,0500,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315-G", deviceJoinName: "Centralite Water Sensor" fingerprint inClusters: "0000,0001,0003,000F,0020,0402,0500", outClusters: "0019", manufacturer: "SmartThings", model: "moisturev4", deviceJoinName: "Water Leak Sensor" } @@ -42,10 +44,10 @@ metadata { preferences { section { image(name: 'educationalcontent', multiple: true, images: [ - "http://cdn.device-gse.smartthings.com/Moisture/Moisture1.png", - "http://cdn.device-gse.smartthings.com/Moisture/Moisture2.png", - "http://cdn.device-gse.smartthings.com/Moisture/Moisture3.png" - ]) + "http://cdn.device-gse.smartthings.com/Moisture/Moisture1.png", + "http://cdn.device-gse.smartthings.com/Moisture/Moisture2.png", + "http://cdn.device-gse.smartthings.com/Moisture/Moisture3.png" + ]) } section { input title: "Temperature Offset", description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter '-5'. If 3 degrees too cold, enter '+3'.", displayDuringSetup: false, type: "paragraph", element: "paragraph" @@ -54,32 +56,32 @@ metadata { } tiles(scale: 2) { - multiAttributeTile(name:"water", type: "generic", width: 6, height: 4){ - tileAttribute ("device.water", key: "PRIMARY_CONTROL") { - attributeState "dry", label: "Dry", icon:"st.alarm.water.dry", backgroundColor:"#ffffff" - attributeState "wet", label: "Wet", icon:"st.alarm.water.wet", backgroundColor:"#53a7c0" + multiAttributeTile(name: "water", type: "generic", width: 6, height: 4) { + tileAttribute("device.water", key: "PRIMARY_CONTROL") { + attributeState "dry", label: "Dry", icon: "st.alarm.water.dry", backgroundColor: "#ffffff" + attributeState "wet", label: "Wet", icon: "st.alarm.water.wet", backgroundColor: "#00A0DC" } } valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2) { - 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"] - ] + 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("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) { - state "battery", label:'${currentValue}% battery', unit:"" + state "battery", label: '${currentValue}% battery', unit: "" } standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { - state "default", action:"refresh.refresh", icon:"st.secondary.refresh" + state "default", action: "refresh.refresh", icon: "st.secondary.refresh" } - main (["water", "temperature"]) + main(["water", "temperature"]) details(["water", "temperature", "battery", "refresh"]) } } @@ -87,117 +89,49 @@ metadata { def parse(String description) { log.debug "description: $description" - Map map = [:] - if (description?.startsWith('catchall:')) { - map = parseCatchAllMessage(description) - } - else if (description?.startsWith('read attr -')) { - map = parseReportAttributeMessage(description) - } - else if (description?.startsWith('temperature: ')) { - map = parseCustomMessage(description) - } - else if (description?.startsWith('zone status')) { - map = parseIasMessage(description) + // getEvent will handle temperature and humidity + Map map = zigbee.getEvent(description) + if (!map) { + if (description?.startsWith('zone status')) { + map = parseIasMessage(description) + } else { + Map descMap = zigbee.parseDescriptionAsMap(description) + if (descMap.clusterInt == 0x0001 && descMap.commandInt != 0x07 && descMap?.value) { + map = getBatteryResult(Integer.parseInt(descMap.value, 16)) + } else if (descMap?.clusterInt == zigbee.TEMPERATURE_MEASUREMENT_CLUSTER && descMap.commandInt == 0x07) { + if (descMap.data[0] == "00") { + log.debug "TEMP REPORTING CONFIG RESPONSE: $descMap" + sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) + } else { + log.warn "TEMP REPORTING CONFIG FAILED- error code: ${descMap.data[0]}" + } + } + } + } else if (map.name == "temperature") { + if (tempOffset) { + map.value = (int) map.value + (int) tempOffset + } + map.descriptionText = temperatureScale == 'C' ? '{{ device.displayName }} was {{ value }}°C' : '{{ device.displayName }} was {{ value }}°F' + map.translatable = true } log.debug "Parse returned $map" def result = map ? createEvent(map) : [:] if (description?.startsWith('enroll request')) { - List cmds = enrollResponse() + List cmds = zigbee.enrollResponse() log.debug "enroll response: ${cmds}" result = cmds?.collect { new physicalgraph.device.HubAction(it) } } return result } -private Map parseCatchAllMessage(String description) { - Map resultMap = [:] - def cluster = zigbee.parse(description) - if (shouldProcessMessage(cluster)) { - switch(cluster.clusterId) { - case 0x0001: - // 0x07 - configure reporting - if (cluster.command != 0x07) { - resultMap = getBatteryResult(cluster.data.last()) - } - break - - case 0x0402: - if (cluster.command == 0x07) { - if (cluster.data[0] == 0x00){ - log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster - resultMap = [name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]] - } - else { - log.warn "TEMP REPORTING CONFIG FAILED- error code:${cluster.data[0]}" - } - } - else { - // temp is last 2 data values. reverse to swap endian - String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join() - def value = getTemperature(temp) - resultMap = getTemperatureResult(value) - } - break - } - } - - return resultMap -} - -private boolean shouldProcessMessage(cluster) { - // 0x0B is default response indicating message got through - boolean ignoredMessage = cluster.profileId != 0x0104 || - cluster.command == 0x0B || - (cluster.data.size() > 0 && cluster.data.first() == 0x3e) - return !ignoredMessage -} - -private Map parseReportAttributeMessage(String description) { - Map descMap = (description - "read attr - ").split(",").inject([:]) { map, param -> - def nameAndValue = param.split(":") - map += [(nameAndValue[0].trim()):nameAndValue[1].trim()] - } - log.debug "Desc Map: $descMap" - - Map resultMap = [:] - if (descMap.cluster == "0402" && descMap.attrId == "0000") { - def value = getTemperature(descMap.value) - resultMap = getTemperatureResult(value) - } - else if (descMap.cluster == "0001" && descMap.attrId == "0020") { - resultMap = getBatteryResult(Integer.parseInt(descMap.value, 16)) - } - - return resultMap -} - -private Map parseCustomMessage(String description) { - Map resultMap = [:] - if (description?.startsWith('temperature: ')) { - def value = zigbee.parseHATemperatureValue(description, "temperature: ", getTemperatureScale()) - resultMap = getTemperatureResult(value) - } - return resultMap -} - private Map parseIasMessage(String description) { ZoneStatus zs = zigbee.parseZoneStatus(description) return zs.isAlarm1Set() ? getMoistureResult('wet') : getMoistureResult('dry') } -def getTemperature(value) { - def celsius = Integer.parseInt(value, 16).shortValue() / 100 - if(getTemperatureScale() == "C"){ - return Math.round(celsius) - } else { - return Math.round(celsiusToFahrenheit(celsius)) - } -} - private Map getBatteryResult(rawValue) { log.debug "Battery rawValue = ${rawValue}" def linkText = getLinkText(device) @@ -238,40 +172,18 @@ private Map getBatteryResult(rawValue) { return result } -private Map getTemperatureResult(value) { - log.debug 'TEMP' - if (tempOffset) { - def offset = tempOffset as int - def v = value as int - value = v + offset - } - def descriptionText - if ( temperatureScale == 'C' ) - descriptionText = '{{ device.displayName }} was {{ value }}°C' - else - descriptionText = '{{ device.displayName }} was {{ value }}°F' - - return [ - name: 'temperature', - value: value, - descriptionText: descriptionText, - translatable: true, - unit: temperatureScale - ] -} - private Map getMoistureResult(value) { log.debug "water" - def descriptionText - if ( value == "wet" ) - descriptionText = '{{ device.displayName }} is wet' - else - descriptionText = '{{ device.displayName }} is dry' + def descriptionText + if (value == "wet") + descriptionText = '{{ device.displayName }} is wet' + else + descriptionText = '{{ device.displayName }} is dry' return [ - name: 'water', - value: value, - descriptionText: descriptionText, - translatable: true + name : 'water', + value : value, + descriptionText: descriptionText, + translatable : true ] } @@ -284,12 +196,10 @@ def ping() { def refresh() { log.debug "Refreshing Temperature and Battery" - def refreshCmds = [ - "st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 200", - "st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 200" - ] + def refreshCmds = zigbee.readAttribute(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0000) + + zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020) - return refreshCmds + enrollResponse() + return refreshCmds + zigbee.enrollResponse() } def configure() { @@ -301,42 +211,3 @@ def configure() { // battery minReport 30 seconds, maxReportTime 6 hrs by default return refresh() + zigbee.batteryConfig() + zigbee.temperatureConfig(30, 300) // send refresh cmds as part of config } - -def enrollResponse() { - log.debug "Sending enroll response" - String zigbeeEui = swapEndianHex(device.hub.zigbeeEui) - [ - //Resending the CIE in case the enroll request is sent before CIE is written - "zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200", - "send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500", - //Enroll Response - "raw 0x500 {01 23 00 00 00}", - "send 0x${device.deviceNetworkId} 1 1", "delay 200" - ] -} - -private getEndpointId() { - new BigInteger(device.endpointId, 16).toString() -} - -private hex(value) { - new BigInteger(Math.round(value).toString()).toString(16) -} - -private String swapEndianHex(String hex) { - reverseArray(hex.decodeHex()).encodeHex() -} - -private byte[] reverseArray(byte[] array) { - int i = 0; - int j = array.length - 1; - byte tmp; - while (j > i) { - tmp = array[j]; - array[j] = array[i]; - array[i] = tmp; - j--; - i++; - } - return array -} diff --git a/devicetypes/smartthings/smartsense-moisture.src/smartsense-moisture.groovy b/devicetypes/smartthings/smartsense-moisture.src/smartsense-moisture.groovy index 43577f1..ebd5888 100644 --- a/devicetypes/smartthings/smartsense-moisture.src/smartsense-moisture.groovy +++ b/devicetypes/smartthings/smartsense-moisture.src/smartsense-moisture.groovy @@ -37,13 +37,13 @@ metadata { multiAttributeTile(name:"water", type: "generic", width: 6, height: 4){ tileAttribute ("device.water", key: "PRIMARY_CONTROL") { attributeState "dry", label: "Dry", icon:"st.alarm.water.dry", backgroundColor:"#ffffff" - attributeState "wet", label: "Wet", icon:"st.alarm.water.wet", backgroundColor:"#53a7c0" + attributeState "wet", label: "Wet", icon:"st.alarm.water.wet", backgroundColor:"#00A0DC" } } standardTile("temperatureState", "device.temperature", width: 2, height: 2) { state "normal", icon:"st.alarm.temperature.normal", backgroundColor:"#ffffff" - state "freezing", icon:"st.alarm.temperature.freeze", backgroundColor:"#53a7c0" - state "overheated", icon:"st.alarm.temperature.overheat", backgroundColor:"#F80000" + state "freezing", icon:"st.alarm.temperature.freeze", backgroundColor:"#00A0DC" + state "overheated", icon:"st.alarm.temperature.overheat", backgroundColor:"#e86d13" } valueTile("temperature", "device.temperature", width: 2, height: 2) { state("temperature", label:'${currentValue}°', diff --git a/devicetypes/smartthings/smartsense-motion-sensor.src/smartsense-motion-sensor.groovy b/devicetypes/smartthings/smartsense-motion-sensor.src/smartsense-motion-sensor.groovy index fa71232..131dca4 100644 --- a/devicetypes/smartthings/smartsense-motion-sensor.src/smartsense-motion-sensor.groovy +++ b/devicetypes/smartthings/smartsense-motion-sensor.src/smartsense-motion-sensor.groovy @@ -17,7 +17,7 @@ import physicalgraph.zigbee.clusters.iaszone.ZoneStatus metadata { - definition (name: "SmartSense Motion Sensor", namespace: "smartthings", author: "SmartThings") { + definition(name: "SmartSense Motion Sensor", namespace: "smartthings", author: "SmartThings") { capability "Motion Sensor" capability "Configuration" capability "Battery" @@ -34,7 +34,9 @@ metadata { fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3325" fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3326" fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3326-L", deviceJoinName: "Iris Motion Sensor" + fingerprint inClusters: "0000,0001,0003,0020,0402,0500,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3328-G", deviceJoinName: "Centralite Micro Motion Sensor" fingerprint inClusters: "0000,0001,0003,000F,0020,0402,0500", outClusters: "0019", manufacturer: "SmartThings", model: "motionv4", deviceJoinName: "Motion Sensor" + fingerprint inClusters: "0000,0001,0003,000F,0020,0402,0500", outClusters: "0019", manufacturer: "SmartThings", model: "motionv5", deviceJoinName: "Motion Sensor" } simulator { @@ -45,10 +47,10 @@ metadata { preferences { section { image(name: 'educationalcontent', multiple: true, images: [ - "http://cdn.device-gse.smartthings.com/Motion/Motion1.jpg", - "http://cdn.device-gse.smartthings.com/Motion/Motion2.jpg", - "http://cdn.device-gse.smartthings.com/Motion/Motion3.jpg" - ]) + "http://cdn.device-gse.smartthings.com/Motion/Motion1.jpg", + "http://cdn.device-gse.smartthings.com/Motion/Motion2.jpg", + "http://cdn.device-gse.smartthings.com/Motion/Motion3.jpg" + ]) } section { input title: "Temperature Offset", description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter '-5'. If 3 degrees too cold, enter '+3'.", displayDuringSetup: false, type: "paragraph", element: "paragraph" @@ -57,30 +59,30 @@ metadata { } tiles(scale: 2) { - multiAttributeTile(name:"motion", type: "generic", width: 6, height: 4){ - tileAttribute ("device.motion", key: "PRIMARY_CONTROL") { - attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0" - attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff" + multiAttributeTile(name: "motion", type: "generic", width: 6, height: 4) { + tileAttribute("device.motion", key: "PRIMARY_CONTROL") { + attributeState "active", label: 'motion', icon: "st.motion.motion.active", backgroundColor: "#53a7c0" + attributeState "inactive", label: 'no motion', icon: "st.motion.motion.inactive", backgroundColor: "#ffffff" } } valueTile("temperature", "device.temperature", width: 2, height: 2) { - state("temperature", label:'${currentValue}°', unit:"F", - 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"] - ] + state("temperature", label: '${currentValue}°', unit: "F", + 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("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) { - state "battery", label:'${currentValue}% battery', unit:"" + state "battery", label: '${currentValue}% battery', unit: "" } standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { - state "default", action:"refresh.refresh", icon:"st.secondary.refresh" + state "default", action: "refresh.refresh", icon: "st.secondary.refresh" } main(["motion", "temperature"]) @@ -90,116 +92,46 @@ metadata { def parse(String description) { log.debug "description: $description" - - Map map = [:] - if (description?.startsWith('catchall:')) { - map = parseCatchAllMessage(description) - } - else if (description?.startsWith('read attr -')) { - map = parseReportAttributeMessage(description) - } - else if (description?.startsWith('temperature: ')) { - map = parseCustomMessage(description) - } - else if (description?.startsWith('zone status')) { - map = parseIasMessage(description) + Map map = zigbee.getEvent(description) + if (!map) { + if (description?.startsWith('zone status')) { + map = parseIasMessage(description) + } else { + Map descMap = zigbee.parseDescriptionAsMap(description) + if (descMap?.clusterInt == 0x0001 && descMap.commandInt != 0x07 && descMap?.value) { + map = getBatteryResult(Integer.parseInt(descMap.value, 16)) + } else if (descMap?.clusterInt == zigbee.TEMPERATURE_MEASUREMENT_CLUSTER && descMap.commandInt == 0x07) { + if (descMap.data[0] == "00") { + log.debug "TEMP REPORTING CONFIG RESPONSE: $descMap" + sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) + } else { + log.warn "TEMP REPORTING CONFIG FAILED- error code: ${descMap.data[0]}" + } + } else if (descMap.clusterInt == 0x0406 && descMap.attrInt == 0x0000) { + def value = descMap.value.endsWith("01") ? "active" : "inactive" + log.debug "Doing a read attr motion event" + map = getMotionResult(value) + } + } + } else if (map.name == "temperature") { + if (tempOffset) { + map.value = (int) map.value + (int) tempOffset + } + map.descriptionText = temperatureScale == 'C' ? '{{ device.displayName }} was {{ value }}°C' : '{{ device.displayName }} was {{ value }}°F' + map.translatable = true } log.debug "Parse returned $map" def result = map ? createEvent(map) : [:] if (description?.startsWith('enroll request')) { - List cmds = enrollResponse() + List cmds = zigbee.enrollResponse() log.debug "enroll response: ${cmds}" result = cmds?.collect { new physicalgraph.device.HubAction(it) } } return result } -private Map parseCatchAllMessage(String description) { - Map resultMap = [:] - def cluster = zigbee.parse(description) - if (shouldProcessMessage(cluster)) { - switch(cluster.clusterId) { - case 0x0001: - // 0x07 - configure reporting - if (cluster.command != 0x07) { - resultMap = getBatteryResult(cluster.data.last()) - } - break - - case 0x0402: - if (cluster.command == 0x07) { - if (cluster.data[0] == 0x00) { - log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster - resultMap = [name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]] - } - else { - log.warn "TEMP REPORTING CONFIG FAILED- error code:${cluster.data[0]}" - } - - } - else { - // temp is last 2 data values. reverse to swap endian - String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join() - def value = getTemperature(temp) - resultMap = getTemperatureResult(value) - } - break - - case 0x0406: - // 0x07 - configure reporting - if (cluster.command != 0x07) { - log.debug 'motion' - resultMap.name = 'motion' - } - break - } - } - - return resultMap -} - -private boolean shouldProcessMessage(cluster) { - // 0x0B is default response indicating message got through - boolean ignoredMessage = cluster.profileId != 0x0104 || - cluster.command == 0x0B || - (cluster.data.size() > 0 && cluster.data.first() == 0x3e) - return !ignoredMessage -} - -private Map parseReportAttributeMessage(String description) { - Map descMap = (description - "read attr - ").split(",").inject([:]) { map, param -> - def nameAndValue = param.split(":") - map += [(nameAndValue[0].trim()):nameAndValue[1].trim()] - } - log.debug "Desc Map: $descMap" - - Map resultMap = [:] - if (descMap.cluster == "0402" && descMap.attrId == "0000") { - def value = getTemperature(descMap.value) - resultMap = getTemperatureResult(value) - } - else if (descMap.cluster == "0001" && descMap.attrId == "0020") { - resultMap = getBatteryResult(Integer.parseInt(descMap.value, 16)) - } - else if (descMap.cluster == "0406" && descMap.attrId == "0000") { - def value = descMap.value.endsWith("01") ? "active" : "inactive" - resultMap = getMotionResult(value) - } - - return resultMap -} - -private Map parseCustomMessage(String description) { - Map resultMap = [:] - if (description?.startsWith('temperature: ')) { - def value = zigbee.parseHATemperatureValue(description, "temperature: ", getTemperatureScale()) - resultMap = getTemperatureResult(value) - } - return resultMap -} - private Map parseIasMessage(String description) { ZoneStatus zs = zigbee.parseZoneStatus(description) @@ -207,15 +139,6 @@ private Map parseIasMessage(String description) { return (zs.isAlarm1Set() || zs.isAlarm2Set()) ? getMotionResult('active') : getMotionResult('inactive') } -def getTemperature(value) { - def celsius = Integer.parseInt(value, 16).shortValue() / 100 - if(getTemperatureScale() == "C"){ - return Math.round(celsius) - } else { - return Math.round(celsiusToFahrenheit(celsius)) - } -} - private Map getBatteryResult(rawValue) { log.debug "Battery rawValue = ${rawValue}" def linkText = getLinkText(device) @@ -255,36 +178,14 @@ private Map getBatteryResult(rawValue) { return result } -private Map getTemperatureResult(value) { - log.debug 'TEMP' - if (tempOffset) { - def offset = tempOffset as int - def v = value as int - value = v + offset - } - def descriptionText - if ( temperatureScale == 'C' ) - descriptionText = '{{ device.displayName }} was {{ value }}°C' - else - descriptionText = '{{ device.displayName }} was {{ value }}°F' - - return [ - name: 'temperature', - value: value, - descriptionText: descriptionText, - translatable: true, - unit: temperatureScale - ] -} - private Map getMotionResult(value) { log.debug 'motion' String descriptionText = value == 'active' ? "{{ device.displayName }} detected motion" : "{{ device.displayName }} motion has stopped" return [ - name: 'motion', - value: value, - descriptionText: descriptionText, - translatable: true + name : 'motion', + value : value, + descriptionText: descriptionText, + translatable : true ] } @@ -292,17 +193,16 @@ private Map getMotionResult(value) { * PING is used by Device-Watch in attempt to reach the Device * */ def ping() { - return zigbee.readAttribute(0x001, 0x0020) // Read the Battery Level + return zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020) // Read the Battery Level } def refresh() { log.debug "refresh called" - def refreshCmds = [ - "st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 200", - "st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 200" - ] - return refreshCmds + enrollResponse() + def refreshCmds = zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020) + + zigbee.readAttribute(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0000) + + return refreshCmds + zigbee.enrollResponse() } def configure() { @@ -314,42 +214,3 @@ def configure() { // battery minReport 30 seconds, maxReportTime 6 hrs by default return refresh() + zigbee.batteryConfig() + zigbee.temperatureConfig(30, 300) // send refresh cmds as part of config } - -def enrollResponse() { - log.debug "Sending enroll response" - String zigbeeEui = swapEndianHex(device.hub.zigbeeEui) - [ - //Resending the CIE in case the enroll request is sent before CIE is written - "zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200", - "send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500", - //Enroll Response - "raw 0x500 {01 23 00 00 00}", - "send 0x${device.deviceNetworkId} 1 1", "delay 200" - ] -} - -private getEndpointId() { - new BigInteger(device.endpointId, 16).toString() -} - -private hex(value) { - new BigInteger(Math.round(value).toString()).toString(16) -} - -private String swapEndianHex(String hex) { - reverseArray(hex.decodeHex()).encodeHex() -} - -private byte[] reverseArray(byte[] array) { - int i = 0; - int j = array.length - 1; - byte tmp; - while (j > i) { - tmp = array[j]; - array[j] = array[i]; - array[i] = tmp; - j--; - i++; - } - return array -} diff --git a/devicetypes/smartthings/smartsense-motion.src/smartsense-motion.groovy b/devicetypes/smartthings/smartsense-motion.src/smartsense-motion.groovy index 5d60112..acb69fa 100644 --- a/devicetypes/smartthings/smartsense-motion.src/smartsense-motion.groovy +++ b/devicetypes/smartthings/smartsense-motion.src/smartsense-motion.groovy @@ -30,8 +30,8 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"motion", type: "generic", width: 6, height: 4){ tileAttribute ("device.motion", key: "PRIMARY_CONTROL") { - attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0" - attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff" + attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC" + attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc" } } valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) { @@ -45,7 +45,7 @@ metadata { def parse(String description) { def results = [:] - if (isZoneType19(description) || !isSupportedDescription(description)) { + if (description.startsWith("zone") || !isSupportedDescription(description)) { results = parseBasicMessage(description) } else if (isMotionStatusMessage(description)){ @@ -87,16 +87,12 @@ private String parseName(String description) { } private String parseValue(String description) { - if (isZoneType19(description)) { - if (translateStatusZoneType19(description)) { - return "active" - } - else { - return "inactive" - } + def zs = zigbee.parseZoneStatus(description) + if (zs) { + zs.isAlarm1Set() ? "active" : "inactive" + } else { + description } - - description } private parseDescriptionText(String linkText, String value, String description) { diff --git a/devicetypes/smartthings/smartsense-multi-sensor.src/smartsense-multi-sensor.groovy b/devicetypes/smartthings/smartsense-multi-sensor.src/smartsense-multi-sensor.groovy index 5cebcd0..62a7fc3 100644 --- a/devicetypes/smartthings/smartsense-multi-sensor.src/smartsense-multi-sensor.groovy +++ b/devicetypes/smartthings/smartsense-multi-sensor.src/smartsense-multi-sensor.groovy @@ -14,24 +14,26 @@ * under the License. */ import physicalgraph.zigbee.clusters.iaszone.ZoneStatus +import physicalgraph.zigbee.zcl.DataType metadata { - definition (name: "SmartSense Multi Sensor", namespace: "smartthings", author: "SmartThings") { + definition(name: "SmartSense Multi Sensor", namespace: "smartthings", author: "SmartThings") { capability "Three Axis" capability "Battery" capability "Configuration" capability "Sensor" - capability "Contact Sensor" - capability "Acceleration Sensor" - capability "Refresh" - capability "Temperature Measurement" + capability "Contact Sensor" + capability "Acceleration Sensor" + capability "Refresh" + capability "Temperature Measurement" capability "Health Check" - command "enrollResponse" - fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05,FC02", outClusters: "0019", manufacturer: "CentraLite", model: "3320" + command "enrollResponse" + fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05,FC02", outClusters: "0019", manufacturer: "CentraLite", model: "3320" fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05,FC02", outClusters: "0019", manufacturer: "CentraLite", model: "3321" fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05,FC02", outClusters: "0019", manufacturer: "CentraLite", model: "3321-S", deviceJoinName: "Multipurpose Sensor" + fingerprint inClusters: "0000,0001,0003,0020,0402,0500,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3323-G", deviceJoinName: "Centralite Micro Door Sensor" fingerprint inClusters: "0000,0001,0003,000F,0020,0402,0500,FC02", outClusters: "0019", manufacturer: "SmartThings", model: "multiv4", deviceJoinName: "Multipurpose Sensor" attribute "status", "string" @@ -57,11 +59,11 @@ metadata { preferences { section { image(name: 'educationalcontent', multiple: true, images: [ - "http://cdn.device-gse.smartthings.com/Multi/Multi1.jpg", - "http://cdn.device-gse.smartthings.com/Multi/Multi2.jpg", - "http://cdn.device-gse.smartthings.com/Multi/Multi3.jpg", - "http://cdn.device-gse.smartthings.com/Multi/Multi4.jpg" - ]) + "http://cdn.device-gse.smartthings.com/Multi/Multi1.jpg", + "http://cdn.device-gse.smartthings.com/Multi/Multi2.jpg", + "http://cdn.device-gse.smartthings.com/Multi/Multi3.jpg", + "http://cdn.device-gse.smartthings.com/Multi/Multi4.jpg" + ]) } section { input title: "Temperature Offset", description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter '-5'. If 3 degrees too cold, enter '+3'.", displayDuringSetup: false, type: "paragraph", element: "paragraph" @@ -73,211 +75,170 @@ metadata { } tiles(scale: 2) { - multiAttributeTile(name:"status", type: "generic", width: 6, height: 4){ - tileAttribute ("device.status", key: "PRIMARY_CONTROL") { - attributeState "open", label:'Open', icon:"st.contact.contact.open", backgroundColor:"#ffa81e" - attributeState "closed", label:'Closed', icon:"st.contact.contact.closed", backgroundColor:"#79b821" - attributeState "garage-open", label:'Open', icon:"st.doors.garage.garage-open", backgroundColor:"#ffa81e" - attributeState "garage-closed", label:'Closed', icon:"st.doors.garage.garage-closed", backgroundColor:"#79b821" + multiAttributeTile(name: "status", type: "generic", width: 6, height: 4) { + tileAttribute("device.status", key: "PRIMARY_CONTROL") { + attributeState "open", label: 'Open', icon: "st.contact.contact.open", backgroundColor: "#e86d13" + attributeState "closed", label: 'Closed', icon: "st.contact.contact.closed", backgroundColor: "#00a0dc" + attributeState "garage-open", label: 'Open', icon: "st.doors.garage.garage-open", backgroundColor: "#e86d13" + attributeState "garage-closed", label: 'Closed', icon: "st.doors.garage.garage-closed", backgroundColor: "#00a0dc" } } standardTile("contact", "device.contact", width: 2, height: 2) { - state("open", label:'Open', icon:"st.contact.contact.open", backgroundColor:"#ffa81e") - state("closed", label:'Closed', icon:"st.contact.contact.closed", backgroundColor:"#79b821") + state("open", label: 'Open', icon: "st.contact.contact.open", backgroundColor: "#e86d13") + state("closed", label: 'Closed', icon: "st.contact.contact.closed", backgroundColor: "#00a0dc") } standardTile("acceleration", "device.acceleration", width: 2, height: 2) { - state("active", label:'Active', icon:"st.motion.acceleration.active", backgroundColor:"#53a7c0") - state("inactive", label:'Inactive', icon:"st.motion.acceleration.inactive", backgroundColor:"#ffffff") + state("active", label: 'Active', icon: "st.motion.acceleration.active", backgroundColor: "#53a7c0") + state("inactive", label: 'Inactive', icon: "st.motion.acceleration.inactive", backgroundColor: "#ffffff") } valueTile("temperature", "device.temperature", width: 2, height: 2) { - 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"] - ] + 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("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) { - state "battery", label:'${currentValue}% battery', unit:"" + state "battery", label: '${currentValue}% battery', unit: "" } standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { - state "default", action:"refresh.refresh", icon:"st.secondary.refresh" + state "default", action: "refresh.refresh", icon: "st.secondary.refresh" } main(["status", "acceleration", "temperature"]) details(["status", "acceleration", "temperature", "battery", "refresh"]) } - } +} def parse(String description) { - Map map = [:] - if (description?.startsWith('catchall:')) { - map = parseCatchAllMessage(description) - } - else if (description?.startsWith('temperature: ')) { - map = parseCustomMessage(description) - } - else if (description?.startsWith('zone status')) { - map = parseIasMessage(description) + def maps = [] + maps << zigbee.getEvent(description) + if (!maps[0]) { + maps = [] + if (description?.startsWith('zone status')) { + maps += parseIasMessage(description) + } else { + Map descMap = zigbee.parseDescriptionAsMap(description) + if (descMap?.clusterInt == 0x0001 && descMap.commandInt != 0x07 && descMap?.value) { + maps << getBatteryResult(Integer.parseInt(descMap.value, 16)) + } else if (descMap?.clusterInt == zigbee.TEMPERATURE_MEASUREMENT_CLUSTER && descMap.commandInt == 0x07) { + if (descMap.data[0] == "00") { + log.debug "TEMP REPORTING CONFIG RESPONSE: $descMap" + sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) + } else { + log.warn "TEMP REPORTING CONFIG FAILED- error code: ${descMap.data[0]}" + } + } else { + + maps += handleAcceleration(descMap) + } + } + } else if (maps[0].name == "temperature") { + def map = maps[0] + if (tempOffset) { + map.value = (int) map.value + (int) tempOffset + } + map.descriptionText = temperatureScale == 'C' ? '{{ device.displayName }} was {{ value }}°C' : '{{ device.displayName }} was {{ value }}°F' + map.translatable = true } - def result = map ? createEvent(map) : [:] - + def result = maps.inject([]) {acc, it -> + if (it) { + acc << createEvent(it) + } + } if (description?.startsWith('enroll request')) { - List cmds = enrollResponse() + List cmds = zigbee.enrollResponse() log.debug "enroll response: ${cmds}" result = cmds?.collect { new physicalgraph.device.HubAction(it) } } - else if (description?.startsWith('read attr -')) { - result = parseReportAttributeMessage(description).each { createEvent(it) } + return result +} + +private List handleAcceleration(descMap) { + def result = [] + if (descMap.clusterInt == 0xFC02 && descMap.attrInt == 0x0010) { + def value = descMap.value == "01" ? "active" : "inactive" + log.debug "Acceleration $value" + result << [ + name : "acceleration", + value : value, + descriptionText: "{{ device.displayName }} was $value", + isStateChange : isStateChange(device, "acceleration", value), + translatable : true + ] + + if (descMap.additionalAttrs) { + result += parseAxis(descMap.additionalAttrs) + } + } else if (descMap.clusterInt == 0xFC02 && descMap.attrInt == 0x0012) { + def addAttrs = descMap.additionalAttrs + addAttrs << ["attrInt": descMap.attrInt, "value": descMap.value] + result += parseAxis(addAttrs) } return result } -private Map parseCatchAllMessage(String description) { - Map resultMap = [:] - def cluster = zigbee.parse(description) - log.debug cluster - if (shouldProcessMessage(cluster)) { - switch(cluster.clusterId) { - case 0x0001: - // 0x07 - configure reporting - if (cluster.command != 0x07) { - resultMap = getBatteryResult(cluster.data.last()) - } - break +private List parseAxis(List attrData) { + def results = [] + def x = hexToSignedInt(attrData.find { it.attrInt == 0x0012 }?.value) + def y = hexToSignedInt(attrData.find { it.attrInt == 0x0013 }?.value) + def z = hexToSignedInt(attrData.find { it.attrInt == 0x0014 }?.value) - case 0xFC02: - log.debug 'ACCELERATION' - break - - case 0x0402: - if (cluster.command == 0x07) { - if(cluster.data[0] == 0x00) { - log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster - resultMap = [name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]] - } - else { - log.warn "TEMP REPORTING CONFIG FAILED- error code:${cluster.data[0]}" - } - } - else { - // temp is last 2 data values. reverse to swap endian - String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join() - def value = getTemperature(temp) - resultMap = getTemperatureResult(value) - } - break - } + def xyzResults = [:] + if (device.getDataValue("manufacturer") == "SmartThings") { + // This mapping matches the current behavior of the Device Handler for the Centralite sensors + xyzResults.x = z + xyzResults.y = y + xyzResults.z = -x + } else { + // The axises reported by the Device Handler differ from the axises reported by the sensor + // This may change in the future + xyzResults.x = z + xyzResults.y = x + xyzResults.z = y } - return resultMap + log.debug "parseAxis -- ${xyzResults}" + + if (garageSensor == "Yes") + results += garageEvent(xyzResults.z) + + def value = "${xyzResults.x},${xyzResults.y},${xyzResults.z}" + results << [ + name : "threeAxis", + value : value, + linkText : getLinkText(device), + descriptionText: "${getLinkText(device)} was ${value}", + handlerName : name, + isStateChange : isStateChange(device, "threeAxis", value), + displayed : false + ] + results } -private boolean shouldProcessMessage(cluster) { - // 0x0B is default response indicating message got through - boolean ignoredMessage = cluster.profileId != 0x0104 || - cluster.command == 0x0B || - (cluster.data.size() > 0 && cluster.data.first() == 0x3e) - return !ignoredMessage -} - -private List parseReportAttributeMessage(String description) { - Map descMap = (description - "read attr - ").split(",").inject([:]) { map, param -> - def nameAndValue = param.split(":") - map += [(nameAndValue[0].trim()):nameAndValue[1].trim()] - } - - List result = [] - if (descMap.cluster == "0402" && descMap.attrId == "0000") { - def value = getTemperature(descMap.value) - result << getTemperatureResult(value) - } - else if (descMap.cluster == "FC02" && descMap.attrId == "0010") { - if (descMap.value.size() == 32) { - // value will look like 00ae29001403e2290013001629001201 - // breaking this apart and swapping byte order where appropriate, this breaks down to: - // X (0x0012) = 0x0016 - // Y (0x0013) = 0x03E2 - // Z (0x0014) = 0x00AE - // note that there is a known bug in that the x,y,z attributes are interpreted in the wrong order - // this will be fixed in a future update - def threeAxisAttributes = descMap.value[0..-9] - result << parseAxis(threeAxisAttributes) - descMap.value = descMap.value[-2..-1] - } - result << getAccelerationResult(descMap.value) - } - else if (descMap.cluster == "FC02" && descMap.attrId == "0012" && descMap.value.size() == 24) { - // The size is checked to ensure the attribute report contains X, Y and Z values - // If all three axis are not included then the attribute report is ignored - result << parseAxis(descMap.value) - } - else if (descMap.cluster == "0001" && descMap.attrId == "0020") { - result << getBatteryResult(Integer.parseInt(descMap.value, 16)) - } - - return result -} - -private Map parseCustomMessage(String description) { - Map resultMap = [:] - if (description?.startsWith('temperature: ')) { - def value = zigbee.parseHATemperatureValue(description, "temperature: ", getTemperatureScale()) - resultMap = getTemperatureResult(value) - } - return resultMap -} - -private Map parseIasMessage(String description) { +private List parseIasMessage(String description) { ZoneStatus zs = zigbee.parseZoneStatus(description) - Map resultMap = [:] + List results = [] - if (garageSensor != "Yes"){ - resultMap = zs.isAlarm1Set() ? getContactResult('open') : getContactResult('closed') - } + if (garageSensor != "Yes") { + def value = zs.isAlarm1Set() ? 'open' : 'closed' + log.debug "Contact: ${device.displayName} value = ${value}" + def descriptionText = value == 'open' ? '{{ device.displayName }} was opened' : '{{ device.displayName }} was closed' + results << [name: 'contact', value: value, descriptionText: descriptionText, displayed: false, translatable: true] + results << [name: 'status', value: value, descriptionText: descriptionText, translatable: true] + } - return resultMap + return results } -def updated() { - log.debug "updated called" - log.info "garage value : $garageSensor" - if (garageSensor == "Yes") { - def descriptionText = "Updating device to garage sensor" - if (device.latestValue("status") == "open") { - sendEvent(name: 'status', value: 'garage-open', descriptionText: descriptionText, translatable: true) - } - else if (device.latestValue("status") == "closed") { - sendEvent(name: 'status', value: 'garage-closed', descriptionText: descriptionText, translatable: true) - } - } - else { - def descriptionText = "Updating device to open/close sensor" - if (device.latestValue("status") == "garage-open") { - sendEvent(name: 'status', value: 'open', descriptionText: descriptionText, translatable: true) - } - else if (device.latestValue("status") == "garage-closed") { - sendEvent(name: 'status', value: 'closed', descriptionText: descriptionText, translatable: true) - } - } -} - -def getTemperature(value) { - def celsius = Integer.parseInt(value, 16).shortValue() / 100 - if(getTemperatureScale() == "C"){ - return Math.round(celsius) - } else { - return Math.round(celsiusToFahrenheit(celsius)) - } - } - private Map getBatteryResult(rawValue) { log.debug "Battery rawValue = ${rawValue}" @@ -316,54 +277,24 @@ private Map getBatteryResult(rawValue) { return result } -private Map getTemperatureResult(value) { - log.debug "Temperature" - if (tempOffset) { - def offset = tempOffset as int - def v = value as int - value = v + offset +List garageEvent(zValue) { + List results = [] + def absValue = zValue.abs() + def contactValue = null + def garageValue = null + if (absValue > 900) { + contactValue = 'closed' + garageValue = 'garage-closed' + } else if (absValue < 100) { + contactValue = 'open' + garageValue = 'garage-open' } - def descriptionText = temperatureScale == 'C' ? '{{ device.displayName }} was {{ value }}°C': - '{{ device.displayName }} was {{ value }}°F' - - return [ - name: 'temperature', - value: value, - descriptionText: descriptionText, - translatable: true, - unit: temperatureScale - ] -} - -private Map getContactResult(value) { - log.debug "Contact: ${device.displayName} value = ${value}" - def descriptionText = value == 'open' ? '{{ device.displayName }} was opened' : '{{ device.displayName }} was closed' - sendEvent(name: 'contact', value: value, descriptionText: descriptionText, displayed: false, translatable: true) - return [name: 'status', value: value, descriptionText: descriptionText, translatable: true] -} - -private getAccelerationResult(numValue) { - log.debug "Acceleration" - def name = "acceleration" - def value - def descriptionText - - if ( numValue.endsWith("1") ) { - value = "active" - descriptionText = '{{ device.displayName }} was active' - } else { - value = "inactive" - descriptionText = '{{ device.displayName }} was inactive' - } - - def isStateChange = isStateChange(device, name, value) - return [ - name: name, - value: value, - descriptionText: descriptionText, - isStateChange: isStateChange, - translatable: true - ] + if (contactValue != null) { + def descriptionText = contactValue == 'open' ? '{{ device.displayName }} was opened' : '{{ device.displayName }} was closed' + results << [name: 'contact', value: contactValue, descriptionText: descriptionText, displayed: false, translatable: true] + results << [name: 'status', value: garageValue, descriptionText: descriptionText, translatable: true] + } + results } /** @@ -376,27 +307,12 @@ def ping() { def refresh() { log.debug "Refreshing Values " - def refreshCmds = [] + def refreshCmds = zigbee.readAttribute(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0000) + + zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020) + + zigbee.readAttribute(0xFC02, 0x0010, [mfgCode: manufacturerCode]) + + zigbee.enrollResponse() - if (device.getDataValue("manufacturer") == "SmartThings") { - log.debug "Refreshing Values for manufacturer: SmartThings " - /* These values of Motion Threshold Multiplier(0x01) and Motion Threshold (0x0276) - seem to be giving pretty accurate results for the XYZ co-ordinates for this manufacturer. - Separating these out in a separate if-else because I do not want to touch Centralite part - as of now. - */ - refreshCmds += zigbee.writeAttribute(0xFC02, 0x0000, 0x20, 0x01, [mfgCode: manufacturerCode]) - refreshCmds += zigbee.writeAttribute(0xFC02, 0x0002, 0x21, 0x0276, [mfgCode: manufacturerCode]) - } else { - refreshCmds += zigbee.writeAttribute(0xFC02, 0x0000, 0x20, 0x02, [mfgCode: manufacturerCode]) - } - - //Common refresh commands - refreshCmds += zigbee.readAttribute(0x0402, 0x0000) + - zigbee.readAttribute(0x0001, 0x0020) + - zigbee.readAttribute(0xFC02, 0x0010, [mfgCode: manufacturerCode]) - - return refreshCmds + enrollResponse() + return refreshCmds } def configure() { @@ -405,61 +321,54 @@ def configure() { sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) log.debug "Configuring Reporting" + def configCmds = [] + + if (device.getDataValue("manufacturer") == "SmartThings") { + log.debug "Refreshing Values for manufacturer: SmartThings " + /* These values of Motion Threshold Multiplier(0x01) and Motion Threshold (0x0276) + seem to be giving pretty accurate results for the XYZ co-ordinates for this manufacturer. + Separating these out in a separate if-else because I do not want to touch Centralite part + as of now. + */ + configCmds += zigbee.writeAttribute(0xFC02, 0x0000, 0x20, 0x01, [mfgCode: manufacturerCode]) + configCmds += zigbee.writeAttribute(0xFC02, 0x0002, 0x21, 0x0276, [mfgCode: manufacturerCode]) + } else { + // Write a motion threshold of 2 * .063g = .126g + // Currently due to a Centralite firmware issue, this will cause a read attribute response that + // indicates acceleration even when there isn't. + configCmds += zigbee.writeAttribute(0xFC02, 0x0000, 0x20, 0x02, [mfgCode: manufacturerCode]) + } // temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity // battery minReport 30 seconds, maxReportTime 6 hrs by default - def configCmds = zigbee.batteryConfig() + + configCmds += zigbee.batteryConfig() + zigbee.temperatureConfig(30, 300) + - zigbee.configureReporting(0xFC02, 0x0010, 0x18, 10, 3600, 0x01, [mfgCode: manufacturerCode]) + - zigbee.configureReporting(0xFC02, 0x0012, 0x29, 1, 3600, 0x0001, [mfgCode: manufacturerCode]) + - zigbee.configureReporting(0xFC02, 0x0013, 0x29, 1, 3600, 0x0001, [mfgCode: manufacturerCode]) + - zigbee.configureReporting(0xFC02, 0x0014, 0x29, 1, 3600, 0x0001, [mfgCode: manufacturerCode]) + zigbee.configureReporting(0xFC02, 0x0010, DataType.BITMAP8, 10, 3600, 0x01, [mfgCode: manufacturerCode]) + + zigbee.configureReporting(0xFC02, 0x0012, DataType.INT16, 1, 3600, 0x0001, [mfgCode: manufacturerCode]) + + zigbee.configureReporting(0xFC02, 0x0013, DataType.INT16, 1, 3600, 0x0001, [mfgCode: manufacturerCode]) + + zigbee.configureReporting(0xFC02, 0x0014, DataType.INT16, 1, 3600, 0x0001, [mfgCode: manufacturerCode]) return refresh() + configCmds } -private getEndpointId() { - new BigInteger(device.endpointId, 16).toString() -} - -def enrollResponse() { - log.debug "Sending enroll response" - String zigbeeEui = swapEndianHex(device.hub.zigbeeEui) - [ - //Resending the CIE in case the enroll request is sent before CIE is written - "zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200", - "send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500", - //Enroll Response - "raw 0x500 {01 23 00 00 00}", "delay 200", - "send 0x${device.deviceNetworkId} 1 1", "delay 200" - ] -} - -private Map parseAxis(String description) { - def z = hexToSignedInt(description[0..3]) - def y = hexToSignedInt(description[10..13]) - def x = hexToSignedInt(description[20..23]) - def xyzResults = [x: x, y: y, z: z] - - if (device.getDataValue("manufacturer") == "SmartThings") { - // This mapping matches the current behavior of the Device Handler for the Centralite sensors - xyzResults.x = z - xyzResults.y = y - xyzResults.z = -x +def updated() { + log.debug "updated called" + log.info "garage value : $garageSensor" + if (garageSensor == "Yes") { + def descriptionText = "Updating device to garage sensor" + if (device.latestValue("status") == "open") { + sendEvent(name: 'status', value: 'garage-open', descriptionText: descriptionText, translatable: true) + } else if (device.latestValue("status") == "closed") { + sendEvent(name: 'status', value: 'garage-closed', descriptionText: descriptionText, translatable: true) + } } else { - // The axises reported by the Device Handler differ from the axises reported by the sensor - // This may change in the future - xyzResults.x = z - xyzResults.y = x - xyzResults.z = y + def descriptionText = "Updating device to open/close sensor" + if (device.latestValue("status") == "garage-open") { + sendEvent(name: 'status', value: 'open', descriptionText: descriptionText, translatable: true) + } else if (device.latestValue("status") == "garage-closed") { + sendEvent(name: 'status', value: 'closed', descriptionText: descriptionText, translatable: true) + } } - - log.debug "parseAxis -- ${xyzResults}" - - if (garageSensor == "Yes") - garageEvent(xyzResults.z) - - getXyzResult(xyzResults, description) } private hexToSignedInt(hexVal) { @@ -467,44 +376,6 @@ private hexToSignedInt(hexVal) { unsignedVal > 32767 ? unsignedVal - 65536 : unsignedVal } -def garageEvent(zValue) { - def absValue = zValue.abs() - def contactValue = null - def garageValue = null - if (absValue>900) { - contactValue = 'closed' - garageValue = 'garage-closed' - } - else if (absValue < 100) { - contactValue = 'open' - garageValue = 'garage-open' - } - if (contactValue != null){ - def descriptionText = contactValue == 'open' ? '{{ device.displayName }} was opened' :'{{ device.displayName }} was closed' - sendEvent(name: 'contact', value: contactValue, descriptionText: descriptionText, displayed:false, translatable: true) - sendEvent(name: 'status', value: garageValue, descriptionText: descriptionText, translatable: true) - } -} - -private Map getXyzResult(results, description) { - def name = "threeAxis" - def value = "${results.x},${results.y},${results.z}" - def linkText = getLinkText(device) - def descriptionText = "$linkText was $value" - def isStateChange = isStateChange(device, name, value) - - [ - name: name, - value: value, - unit: null, - linkText: linkText, - descriptionText: descriptionText, - handlerName: name, - isStateChange: isStateChange, - displayed: false - ] -} - private getManufacturerCode() { if (device.getDataValue("manufacturer") == "SmartThings") { return "0x110A" @@ -516,25 +387,3 @@ private getManufacturerCode() { private hexToInt(value) { new BigInteger(value, 16) } - -private hex(value) { - new BigInteger(Math.round(value).toString()).toString(16) -} - -private String swapEndianHex(String hex) { - reverseArray(hex.decodeHex()).encodeHex() -} - -private byte[] reverseArray(byte[] array) { - int i = 0; - int j = array.length - 1; - byte tmp; - while (j > i) { - tmp = array[j]; - array[j] = array[i]; - array[i] = tmp; - j--; - i++; - } - return array -} diff --git a/devicetypes/smartthings/smartsense-multi.src/smartsense-multi.groovy b/devicetypes/smartthings/smartsense-multi.src/smartsense-multi.groovy index 17f5ddd..328c9a7 100644 --- a/devicetypes/smartthings/smartsense-multi.src/smartsense-multi.groovy +++ b/devicetypes/smartthings/smartsense-multi.src/smartsense-multi.groovy @@ -52,14 +52,14 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"contact", type: "generic", width: 6, height: 4){ tileAttribute ("device.contact", key: "PRIMARY_CONTROL") { - attributeState "open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e" - attributeState "closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821" + attributeState "open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"##e86d13" + attributeState "closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#00a0dc" } } standardTile("acceleration", "device.acceleration", width: 2, height: 2) { - state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#53a7c0") - state("inactive", label:'${name}', icon:"st.motion.acceleration.inactive", backgroundColor:"#ffffff") + state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#00a0dc") + state("inactive", label:'${name}', icon:"st.motion.acceleration.inactive", backgroundColor:"#cccccc") } valueTile("temperature", "device.temperature", width: 2, height: 2) { state("temperature", label:'${currentValue}°', @@ -86,7 +86,7 @@ metadata { def parse(String description) { def results - if (!isSupportedDescription(description) || zigbee.isZoneType19(description)) { + if (!isSupportedDescription(description) || description.startsWith("zone")) { results = parseSingleMessage(description) } else if (description == 'updated') { @@ -488,12 +488,7 @@ private String parseValue(String description) { if (!isSupportedDescription(description)) { return description } - else if (zigbee.translateStatusZoneType19(description)) { - return "open" - } - else { - return "closed" - } + return zigbee.parseZoneStatus(description)?.isAlarm1Set() ? "open" : "closed" } private parseDescriptionText(String linkText, String value, String description) { diff --git a/devicetypes/smartthings/smartsense-open-closed-sensor.src/smartsense-open-closed-sensor.groovy b/devicetypes/smartthings/smartsense-open-closed-sensor.src/smartsense-open-closed-sensor.groovy index b8c9196..fc08a0a 100644 --- a/devicetypes/smartthings/smartsense-open-closed-sensor.src/smartsense-open-closed-sensor.groovy +++ b/devicetypes/smartthings/smartsense-open-closed-sensor.src/smartsense-open-closed-sensor.groovy @@ -16,7 +16,7 @@ import physicalgraph.zigbee.clusters.iaszone.ZoneStatus metadata { - definition (name: "SmartSense Open/Closed Sensor", namespace: "smartthings", author: "SmartThings") { + definition(name: "SmartSense Open/Closed Sensor", namespace: "smartthings", author: "SmartThings") { capability "Battery" capability "Configuration" capability "Contact Sensor" @@ -43,155 +43,83 @@ metadata { } tiles(scale: 2) { - multiAttributeTile(name:"contact", type: "generic", width: 6, height: 4){ - tileAttribute ("device.contact", key: "PRIMARY_CONTROL") { - attributeState "open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e" - attributeState "closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821" + multiAttributeTile(name: "contact", type: "generic", width: 6, height: 4) { + tileAttribute("device.contact", key: "PRIMARY_CONTROL") { + attributeState "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#e86d13" + attributeState "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#00A0DC" } } valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2) { - 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"] - ] + 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("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) { - state "battery", label:'${currentValue}% battery', unit:"" + state "battery", label: '${currentValue}% battery', unit: "" } standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { - state "default", action:"refresh.refresh", icon:"st.secondary.refresh" + state "default", action: "refresh.refresh", icon: "st.secondary.refresh" } - main (["contact", "temperature"]) - details(["contact","temperature","battery","refresh"]) + main(["contact", "temperature"]) + details(["contact", "temperature", "battery", "refresh"]) } } def parse(String description) { log.debug "description: $description" - Map map = [:] - if (description?.startsWith('catchall:')) { - map = parseCatchAllMessage(description) + Map map = zigbee.getEvent(description) + if (!map) { + if (description?.startsWith('zone status')) { + map = parseIasMessage(description) + } else { + Map descMap = zigbee.parseDescriptionAsMap(description) + if (descMap?.clusterInt == 0x0001 && descMap.commandInt != 0x07 && descMap?.value) { + map = getBatteryResult(Integer.parseInt(descMap.value, 16)) + } else if (descMap?.clusterInt == zigbee.TEMPERATURE_MEASUREMENT_CLUSTER && descMap.commandInt == 0x07) { + if (descMap.data[0] == "00") { + log.debug "TEMP REPORTING CONFIG RESPONSE: $descMap" + sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) + } else { + log.warn "TEMP REPORTING CONFIG FAILED- error code: ${descMap.data[0]}" + } + } + } + } else if (map.name == "temperature") { + if (tempOffset) { + map.value = (int) map.value + (int) tempOffset + } + map.descriptionText = temperatureScale == 'C' ? '{{ device.displayName }} was {{ value }}°C' : '{{ device.displayName }} was {{ value }}°F' + map.translatable = true } - else if (description?.startsWith('read attr -')) { - map = parseReportAttributeMessage(description) - } - else if (description?.startsWith('temperature: ')) { - map = parseCustomMessage(description) - } - else if (description?.startsWith('zone status')) { - map = parseIasMessage(description) - } log.debug "Parse returned $map" def result = map ? createEvent(map) : [:] - if (description?.startsWith('enroll request')) { - List cmds = enrollResponse() - log.debug "enroll response: ${cmds}" - result = cmds?.collect { new physicalgraph.device.HubAction(it) } - } - return result -} - -private Map parseCatchAllMessage(String description) { - Map resultMap = [:] - def cluster = zigbee.parse(description) - if (shouldProcessMessage(cluster)) { - switch(cluster.clusterId) { - case 0x0001: - // 0x07 - configure reporting - if (cluster.command != 0x07) { - resultMap = getBatteryResult(cluster.data.last()) - } - break - - case 0x0402: - if (cluster.command == 0x07){ - if (cluster.data[0] == 0x00) { - log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster - resultMap = [name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]] - } - else { - log.warn "TEMP REPORTING CONFIG FAILED- error code:${cluster.data[0]}" - } - } - else { - // temp is last 2 data values. reverse to swap endian - String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join() - def value = getTemperature(temp) - resultMap = getTemperatureResult(value) - } - break - } - } - - return resultMap -} - -private boolean shouldProcessMessage(cluster) { - // 0x0B is default response indicating message got through - boolean ignoredMessage = cluster.profileId != 0x0104 || - cluster.command == 0x0B || - (cluster.data.size() > 0 && cluster.data.first() == 0x3e) - return !ignoredMessage -} - -private int getHumidity(value) { - return Math.round(Double.parseDouble(value)) -} - -private Map parseReportAttributeMessage(String description) { - Map descMap = (description - "read attr - ").split(",").inject([:]) { map, param -> - def nameAndValue = param.split(":") - map += [(nameAndValue[0].trim()):nameAndValue[1].trim()] + if (description?.startsWith('enroll request')) { + List cmds = zigbee.enrollResponse() + log.debug "enroll response: ${cmds}" + result = cmds?.collect { new physicalgraph.device.HubAction(it) } } - log.debug "Desc Map: $descMap" - - Map resultMap = [:] - if (descMap.cluster == "0402" && descMap.attrId == "0000") { - def value = getTemperature(descMap.value) - resultMap = getTemperatureResult(value) - } - else if (descMap.cluster == "0001" && descMap.attrId == "0020") { - resultMap = getBatteryResult(Integer.parseInt(descMap.value, 16)) - } - - return resultMap + return result } -private Map parseCustomMessage(String description) { - Map resultMap = [:] - if (description?.startsWith('temperature: ')) { - def value = zigbee.parseHATemperatureValue(description, "temperature: ", getTemperatureScale()) - resultMap = getTemperatureResult(value) - } - return resultMap -} private Map parseIasMessage(String description) { ZoneStatus zs = zigbee.parseZoneStatus(description) return zs.isAlarm1Set() ? getContactResult('open') : getContactResult('closed') } -def getTemperature(value) { - def celsius = Integer.parseInt(value, 16).shortValue() / 100 - if(getTemperatureScale() == "C"){ - return celsius - } else { - return celsiusToFahrenheit(celsius) as Integer - } -} - private Map getBatteryResult(rawValue) { log.debug 'Battery' def linkText = getLinkText(device) @@ -204,8 +132,8 @@ private Map getBatteryResult(rawValue) { def maxVolts = 3.0 def pct = (volts - minVolts) / (maxVolts - minVolts) def roundedPct = Math.round(pct * 100) - if (roundedPct <= 0) - roundedPct = 1 + if (roundedPct <= 0) + roundedPct = 1 result.value = Math.min(100, roundedPct) result.descriptionText = "${linkText} battery was ${result.value}%" result.name = 'battery' @@ -214,31 +142,14 @@ private Map getBatteryResult(rawValue) { return result } -private Map getTemperatureResult(value) { - log.debug 'TEMP' - def linkText = getLinkText(device) - if (tempOffset) { - def offset = tempOffset as int - def v = value as int - value = v + offset - } - def descriptionText = "${linkText} was ${value}°${temperatureScale}" - return [ - name: 'temperature', - value: value, - descriptionText: descriptionText, - unit: temperatureScale - ] -} - private Map getContactResult(value) { log.debug 'Contact Status' def linkText = getLinkText(device) def descriptionText = "${linkText} was ${value == 'open' ? 'opened' : 'closed'}" return [ - name: 'contact', - value: value, - descriptionText: descriptionText + name : 'contact', + value : value, + descriptionText: descriptionText ] } @@ -251,12 +162,10 @@ def ping() { def refresh() { log.debug "Refreshing Temperature and Battery" - def refreshCmds = [ - "st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 200", - "st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 200" - ] + def refreshCmds = zigbee.readAttribute(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0000) + + zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020) - return refreshCmds + enrollResponse() + return refreshCmds + zigbee.enrollResponse() } def configure() { @@ -268,44 +177,5 @@ def configure() { // temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity // battery minReport 30 seconds, maxReportTime 6 hrs by default - return refresh() + zigbee.batteryConfig() + zigbee.temperatureConfig(30, 300) // send refresh cmds as part of config -} - -def enrollResponse() { - log.debug "Sending enroll response" - String zigbeeEui = swapEndianHex(device.hub.zigbeeEui) - [ - //Resending the CIE in case the enroll request is sent before CIE is written - "zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200", - "send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500", - //Enroll Response - "raw 0x500 {01 23 00 00 00}", - "send 0x${device.deviceNetworkId} 1 1", "delay 200" - ] -} - -private getEndpointId() { - new BigInteger(device.endpointId, 16).toString() -} - -private hex(value) { - new BigInteger(Math.round(value).toString()).toString(16) -} - -private String swapEndianHex(String hex) { - reverseArray(hex.decodeHex()).encodeHex() -} - -private byte[] reverseArray(byte[] array) { - int i = 0; - int j = array.length - 1; - byte tmp; - while (j > i) { - tmp = array[j]; - array[j] = array[i]; - array[i] = tmp; - j--; - i++; - } - return array + return refresh() + zigbee.batteryConfig() + zigbee.temperatureConfig(30, 300) // send refresh cmds as part of config } diff --git a/devicetypes/smartthings/smartsense-temp-humidity-sensor.src/smartsense-temp-humidity-sensor.groovy b/devicetypes/smartthings/smartsense-temp-humidity-sensor.src/smartsense-temp-humidity-sensor.groovy index cd9648e..a655c21 100644 --- a/devicetypes/smartthings/smartsense-temp-humidity-sensor.src/smartsense-temp-humidity-sensor.groovy +++ b/devicetypes/smartthings/smartsense-temp-humidity-sensor.src/smartsense-temp-humidity-sensor.groovy @@ -13,8 +13,10 @@ * for the specific language governing permissions and limitations under the License. * */ +import physicalgraph.zigbee.zcl.DataType + metadata { - definition (name: "SmartSense Temp/Humidity Sensor",namespace: "smartthings", author: "SmartThings") { + definition(name: "SmartSense Temp/Humidity Sensor", namespace: "smartthings", author: "SmartThings") { capability "Configuration" capability "Battery" capability "Refresh" @@ -31,7 +33,7 @@ metadata { status 'H 45': 'catchall: 0104 FC45 01 01 0140 00 D9B9 00 04 C2DF 0A 01 0000218911' status 'H 57': 'catchall: 0104 FC45 01 01 0140 00 4E55 00 04 C2DF 0A 01 0000211316' status 'H 53': 'catchall: 0104 FC45 01 01 0140 00 20CD 00 04 C2DF 0A 01 0000219814' - status 'H 43': 'read attr - raw: BF7601FC450C00000021A410, dni: BF76, endpoint: 01, cluster: FC45, size: 0C, attrId: 0000, result: success, encoding: 21, value: 10a4' + status 'H 43': 'read attr - raw: BF7601FC450C00000021A410, dni: BF76, endpoint: 01, cluster: FC45, size: 0C, attrId: 0000, result: success, encoding: 21, value: 10a4' } preferences { @@ -40,28 +42,28 @@ metadata { } tiles(scale: 2) { - multiAttributeTile(name:"temperature", type: "generic", width: 6, height: 4){ - tileAttribute ("device.temperature", key: "PRIMARY_CONTROL") { - attributeState "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"] - ] + multiAttributeTile(name: "temperature", type: "generic", width: 6, height: 4) { + tileAttribute("device.temperature", key: "PRIMARY_CONTROL") { + attributeState "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("humidity", "device.humidity", inactiveLabel: false, width: 2, height: 2) { - state "humidity", label:'${currentValue}% humidity', unit:"" + state "humidity", label: '${currentValue}% humidity', unit: "" } valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) { - state "battery", label:'${currentValue}% battery' + state "battery", label: '${currentValue}% battery' } standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { - state "default", action:"refresh.refresh", icon:"st.secondary.refresh" + state "default", action: "refresh.refresh", icon: "st.secondary.refresh" } main "temperature", "humidity" @@ -72,142 +74,37 @@ metadata { def parse(String description) { log.debug "description: $description" - Map map = [:] - if (description?.startsWith('catchall:')) { - map = parseCatchAllMessage(description) - } - else if (description?.startsWith('read attr -')) { - map = parseReportAttributeMessage(description) - } - else if (description?.startsWith('temperature: ') || description?.startsWith('humidity: ')) { - map = parseCustomMessage(description) + // getEvent will handle temperature and humidity + Map map = zigbee.getEvent(description) + if (!map) { + Map descMap = zigbee.parseDescriptionAsMap(description) + if (descMap.clusterInt == 0x0001 && descMap.commandInt != 0x07 && descMap?.value) { + map = getBatteryResult(Integer.parseInt(descMap.value, 16)) + } else if (descMap?.clusterInt == zigbee.TEMPERATURE_MEASUREMENT_CLUSTER && descMap.commandInt == 0x07) { + if (descMap.data[0] == "00") { + log.debug "TEMP REPORTING CONFIG RESPONSE: $descMap" + sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) + } else { + log.warn "TEMP REPORTING CONFIG FAILED- error code: ${descMap.data[0]}" + } + } + } else if (map.name == "temperature") { + if (tempOffset) { + map.value = (int) map.value + (int) tempOffset + } + map.descriptionText = temperatureScale == 'C' ? '{{ device.displayName }} was {{ value }}°C' : '{{ device.displayName }} was {{ value }}°F' + map.translatable = true } log.debug "Parse returned $map" return map ? createEvent(map) : [:] } -private Map parseCatchAllMessage(String description) { - Map resultMap = [:] - def cluster = zigbee.parse(description) - if (shouldProcessMessage(cluster)) { - switch(cluster.clusterId) { - case 0x0001: - // 0x07 - configure reporting - if (cluster.command != 0x07) { - resultMap = getBatteryResult(cluster.data.last()) - } - break - - case 0x0402: - if (cluster.command == 0x07) { - if (cluster.data[0] == 0x00){ - log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster - resultMap = [name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]] - } - else { - log.warn "TEMP REPORTING CONFIG FAILED- error code:${cluster.data[0]}" - } - } - else { - // temp is last 2 data values. reverse to swap endian - String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join() - def value = getTemperature(temp) - resultMap = getTemperatureResult(value) - } - break - - case 0xFC45: - // 0x07 - configure reporting - if (cluster.command != 0x07) { - String pctStr = cluster.data[-1, -2].collect { Integer.toHexString(it) }.join('') - String display = Math.round(Integer.valueOf(pctStr, 16) / 100) - resultMap = getHumidityResult(display) - } - break - } - } - - return resultMap -} - -private boolean shouldProcessMessage(cluster) { - // 0x0B is default response indicating message got through - boolean ignoredMessage = cluster.profileId != 0x0104 || - cluster.command == 0x0B || - (cluster.data.size() > 0 && cluster.data.first() == 0x3e) - return !ignoredMessage -} - -private Map parseReportAttributeMessage(String description) { - Map descMap = (description - "read attr - ").split(",").inject([:]) { map, param -> - def nameAndValue = param.split(":") - map += [(nameAndValue[0].trim()):nameAndValue[1].trim()] - } - log.debug "Desc Map: $descMap" - - Map resultMap = [:] - if (descMap.cluster == "0402" && descMap.attrId == "0000") { - def value = getTemperature(descMap.value) - resultMap = getTemperatureResult(value) - } - else if (descMap.cluster == "0001" && descMap.attrId == "0020") { - resultMap = getBatteryResult(Integer.parseInt(descMap.value, 16)) - } - else if (descMap.cluster == "FC45" && descMap.attrId == "0000") { - def value = getReportAttributeHumidity(descMap.value) - resultMap = getHumidityResult(value) - } - - return resultMap -} - -def getReportAttributeHumidity(String value) { - def humidity = null - if (value?.trim()) { - try { - // value is hex with no decimal - def pct = Integer.parseInt(value.trim(), 16) / 100 - humidity = String.format('%.0f', pct) - } catch(NumberFormatException nfe) { - log.debug "Error converting $value to humidity" - } - } - return humidity -} - -private Map parseCustomMessage(String description) { - Map resultMap = [:] - if (description?.startsWith('temperature: ')) { - def value = zigbee.parseHATemperatureValue(description, "temperature: ", getTemperatureScale()) - resultMap = getTemperatureResult(value) - } - else if (description?.startsWith('humidity: ')) { - def pct = (description - "humidity: " - "%").trim() - if (pct.isNumber()) { - def value = Math.round(new BigDecimal(pct)).toString() - resultMap = getHumidityResult(value) - } else { - log.error "invalid humidity: ${pct}" - } - } - return resultMap -} - -def getTemperature(value) { - def celsius = Integer.parseInt(value, 16).shortValue() / 100 - if(getTemperatureScale() == "C"){ - return celsius - } else { - return celsiusToFahrenheit(celsius) as Integer - } -} - private Map getBatteryResult(rawValue) { log.debug 'Battery' def linkText = getLinkText(device) - def result = [:] + def result = [:] def volts = rawValue / 10 if (!(rawValue == 0 || rawValue == 255)) { @@ -226,41 +123,22 @@ private Map getBatteryResult(rawValue) { return result } -private Map getTemperatureResult(value) { - log.debug 'TEMP' - def linkText = getLinkText(device) - if (tempOffset) { - def offset = tempOffset as int - def v = value as int - value = v + offset - } - def descriptionText = "${linkText} was ${value}°${temperatureScale}" - return [ - name: 'temperature', - value: value, - descriptionText: descriptionText, - unit: temperatureScale - ] -} - -private Map getHumidityResult(value) { - log.debug 'Humidity' - return value ? [name: 'humidity', value: value, unit: '%'] : [:] -} - /** * PING is used by Device-Watch in attempt to reach the Device * */ def ping() { - return zigbee.readAttribute(0x001, 0x0020) // Read the Battery Level + return zigbee.readAttribute(0x0001, 0x0020) // Read the Battery Level } -def refresh() -{ +def refresh() { log.debug "refresh temperature, humidity, and battery" - return zigbee.readAttribute(0xFC45, 0x0000, ["mfgCode": 0xC2DF]) + // Original firmware - zigbee.readAttribute(0x0402, 0x0000) + - zigbee.readAttribute(0x0001, 0x0020) + return zigbee.readAttribute(0xFC45, 0x0000, ["mfgCode": 0x104E]) + // New firmware + zigbee.readAttribute(0xFC45, 0x0000, ["mfgCode": 0xC2DF]) + // Original firmware + zigbee.readAttribute(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0000) + + zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020) + + zigbee.configureReporting(0xFC45, 0x0000, DataType.INT16, 30, 3600, 100) + + zigbee.batteryConfig() + + zigbee.temperatureConfig(30, 300) } def configure() { @@ -269,35 +147,8 @@ def configure() { sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) log.debug "Configuring Reporting and Bindings." - def humidityConfigCmds = [ - "zdo bind 0x${device.deviceNetworkId} 1 1 0xFC45 {${device.zigbeeId}} {}", "delay 500", - "zcl global send-me-a-report 0xFC45 0 0x29 30 3600 {6400}", - "send 0x${device.deviceNetworkId} 1 1", "delay 500" - ] // temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity // battery minReport 30 seconds, maxReportTime 6 hrs by default - return refresh() + humidityConfigCmds + zigbee.batteryConfig() + zigbee.temperatureConfig(30, 300) // send refresh cmds as part of config -} - -private hex(value) { - new BigInteger(Math.round(value).toString()).toString(16) -} - -private String swapEndianHex(String hex) { - reverseArray(hex.decodeHex()).encodeHex() -} - -private byte[] reverseArray(byte[] array) { - int i = 0; - int j = array.length - 1; - byte tmp; - while (j > i) { - tmp = array[j]; - array[j] = array[i]; - array[i] = tmp; - j--; - i++; - } - return array + return refresh() } diff --git a/devicetypes/smartthings/smartsense-virtual-open-closed.src/smartsense-virtual-open-closed.groovy b/devicetypes/smartthings/smartsense-virtual-open-closed.src/smartsense-virtual-open-closed.groovy index 0d4d137..4ffc9a2 100644 --- a/devicetypes/smartthings/smartsense-virtual-open-closed.src/smartsense-virtual-open-closed.groovy +++ b/devicetypes/smartthings/smartsense-virtual-open-closed.src/smartsense-virtual-open-closed.groovy @@ -51,12 +51,12 @@ metadata { 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") + state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#e86d13") + state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#00a0dc") } standardTile("acceleration", "device.acceleration") { - state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#53a7c0") - state("inactive", label:'${name}', icon:"st.motion.acceleration.inactive", backgroundColor:"#ffffff") + state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#00a0dc") + state("inactive", label:'${name}', icon:"st.motion.acceleration.inactive", backgroundColor:"#cccccc") } valueTile("temperature", "device.temperature") { state("temperature", label:'${currentValue}°', @@ -96,7 +96,7 @@ metadata { def parse(String description) { def results - if (!isSupportedDescription(description) || zigbee.isZoneType19(description)) { + if (!isSupportedDescription(description) || description.startsWith("zone")) { // Ignore this in favor of orientation-based state // results = parseSingleMessage(description) } diff --git a/devicetypes/smartthings/spark.src/spark.groovy b/devicetypes/smartthings/spark.src/spark.groovy index 3f74ce4..84e08d5 100644 --- a/devicetypes/smartthings/spark.src/spark.groovy +++ b/devicetypes/smartthings/spark.src/spark.groovy @@ -20,7 +20,7 @@ metadata { // tile definitions tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { - state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" + state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC" state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" } diff --git a/devicetypes/smartthings/sylvania-ultra-iq.src/sylvania-ultra-iq.groovy b/devicetypes/smartthings/sylvania-ultra-iq.src/sylvania-ultra-iq.groovy index 4058ff6..1916ada 100644 --- a/devicetypes/smartthings/sylvania-ultra-iq.src/sylvania-ultra-iq.groovy +++ b/devicetypes/smartthings/sylvania-ultra-iq.src/sylvania-ultra-iq.groovy @@ -36,7 +36,7 @@ metadata { tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" - state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" + state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00a0dc" } controlTile("levelSliderControl", "device.level", "slider", height: 2, width: 1, inactiveLabel: false) { state "level", action:"switch level.setLevel" diff --git a/devicetypes/smartthings/testing/simulated-contact-sensor.src/simulated-contact-sensor.groovy b/devicetypes/smartthings/testing/simulated-contact-sensor.src/simulated-contact-sensor.groovy index 0c520e8..5fa041e 100644 --- a/devicetypes/smartthings/testing/simulated-contact-sensor.src/simulated-contact-sensor.groovy +++ b/devicetypes/smartthings/testing/simulated-contact-sensor.src/simulated-contact-sensor.groovy @@ -28,8 +28,8 @@ metadata { tiles { standardTile("contact", "device.contact", width: 2, height: 2) { - state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821", action: "open") - state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e", action: "close") + state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#00A0DC", action: "open") + state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#e86d13", action: "close") } main "contact" details "contact" diff --git a/devicetypes/smartthings/testing/simulated-garage-door-opener.src/simulated-garage-door-opener.groovy b/devicetypes/smartthings/testing/simulated-garage-door-opener.src/simulated-garage-door-opener.groovy index a54c567..3b37682 100644 --- a/devicetypes/smartthings/testing/simulated-garage-door-opener.src/simulated-garage-door-opener.groovy +++ b/devicetypes/smartthings/testing/simulated-garage-door-opener.src/simulated-garage-door-opener.groovy @@ -29,10 +29,10 @@ metadata { tiles { standardTile("toggle", "device.door", width: 2, height: 2) { - state("closed", label:'${name}', action:"door control.open", icon:"st.doors.garage.garage-closed", backgroundColor:"#79b821", nextState:"opening") - state("open", label:'${name}', action:"door control.close", icon:"st.doors.garage.garage-open", backgroundColor:"#ffa81e", nextState:"closing") - state("opening", label:'${name}', icon:"st.doors.garage.garage-closed", backgroundColor:"#ffe71e") - state("closing", label:'${name}', icon:"st.doors.garage.garage-open", backgroundColor:"#ffe71e") + state("closed", label:'${name}', action:"door control.open", icon:"st.doors.garage.garage-closed", backgroundColor:"#00A0DC", nextState:"opening") + state("open", label:'${name}', action:"door control.close", icon:"st.doors.garage.garage-open", backgroundColor:"#e86d13", nextState:"closing") + state("opening", label:'${name}', icon:"st.doors.garage.garage-closed", backgroundColor:"#e86d13") + state("closing", label:'${name}', icon:"st.doors.garage.garage-open", backgroundColor:"#00A0DC") } standardTile("open", "device.door", inactiveLabel: false, decoration: "flat") { diff --git a/devicetypes/smartthings/testing/simulated-lock.src/simulated-lock.groovy b/devicetypes/smartthings/testing/simulated-lock.src/simulated-lock.groovy index 59e6e0d..775abbb 100644 --- a/devicetypes/smartthings/testing/simulated-lock.src/simulated-lock.groovy +++ b/devicetypes/smartthings/testing/simulated-lock.src/simulated-lock.groovy @@ -23,7 +23,7 @@ metadata { tiles { standardTile("toggle", "device.lock", width: 2, height: 2) { state "unlocked", label:'unlocked', action:"lock.lock", icon:"st.locks.lock.unlocked", backgroundColor:"#ffffff" - state "locked", label:'locked', action:"lock.unlock", icon:"st.locks.lock.locked", backgroundColor:"#79b821" + state "locked", label:'locked', action:"lock.unlock", icon:"st.locks.lock.locked", backgroundColor:"#00A0DC" } standardTile("lock", "device.lock", inactiveLabel: false, decoration: "flat") { state "default", label:'lock', action:"lock.lock", icon:"st.locks.lock.locked" diff --git a/devicetypes/smartthings/testing/simulated-motion-sensor.src/simulated-motion-sensor.groovy b/devicetypes/smartthings/testing/simulated-motion-sensor.src/simulated-motion-sensor.groovy index cf5a773..3776ab5 100644 --- a/devicetypes/smartthings/testing/simulated-motion-sensor.src/simulated-motion-sensor.groovy +++ b/devicetypes/smartthings/testing/simulated-motion-sensor.src/simulated-motion-sensor.groovy @@ -28,8 +28,8 @@ metadata { tiles { standardTile("motion", "device.motion", width: 2, height: 2) { - state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff", action: "active") - state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0", action: "inactive") + state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc", action: "active") + state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC", action: "inactive") } main "motion" details "motion" diff --git a/devicetypes/smartthings/testing/simulated-presence-sensor.src/simulated-presence-sensor.groovy b/devicetypes/smartthings/testing/simulated-presence-sensor.src/simulated-presence-sensor.groovy index 389122a..b7ef6ca 100644 --- a/devicetypes/smartthings/testing/simulated-presence-sensor.src/simulated-presence-sensor.groovy +++ b/devicetypes/smartthings/testing/simulated-presence-sensor.src/simulated-presence-sensor.groovy @@ -29,7 +29,7 @@ metadata { tiles { standardTile("presence", "device.presence", width: 2, height: 2, canChangeBackground: true) { state("not present", label:'not present', icon:"st.presence.tile.not-present", backgroundColor:"#ffffff", action:"arrived") - state("present", label:'present', icon:"st.presence.tile.present", backgroundColor:"#53a7c0", action:"departed") + state("present", label:'present', icon:"st.presence.tile.present", backgroundColor:"#00A0DC", action:"departed") } main "presence" details "presence" diff --git a/devicetypes/smartthings/testing/simulated-switch.src/simulated-switch.groovy b/devicetypes/smartthings/testing/simulated-switch.src/simulated-switch.groovy index e15cf0d..8bf8088 100644 --- a/devicetypes/smartthings/testing/simulated-switch.src/simulated-switch.groovy +++ b/devicetypes/smartthings/testing/simulated-switch.src/simulated-switch.groovy @@ -12,7 +12,7 @@ * */ metadata { - + definition (name: "Simulated Switch", namespace: "smartthings/testing", author: "bob") { capability "Switch" capability "Relay Switch" @@ -26,7 +26,7 @@ metadata { tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { state "off", label: '${currentValue}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" - state "on", label: '${currentValue}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" + state "on", label: '${currentValue}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC" } standardTile("on", "device.switch", decoration: "flat") { state "default", label: 'On', action: "onPhysical", backgroundColor: "#ffffff" @@ -39,9 +39,7 @@ metadata { } } -def parse(String description) { - def pair = description.split(":") - createEvent(name: pair[0].trim(), value: pair[1].trim()) +def parse(description) { } def on() { diff --git a/devicetypes/smartthings/testing/simulated-thermostat.src/simulated-thermostat.groovy b/devicetypes/smartthings/testing/simulated-thermostat.src/simulated-thermostat.groovy index 63d08f8..998dba9 100644 --- a/devicetypes/smartthings/testing/simulated-thermostat.src/simulated-thermostat.groovy +++ b/devicetypes/smartthings/testing/simulated-thermostat.src/simulated-thermostat.groovy @@ -101,9 +101,9 @@ metadata { standardTile("mode", "device.thermostatMode", width: 2, height: 2, inactiveLabel: false, decoration: "flat") { state "off", label:'${name}', action:"thermostat.heat", backgroundColor:"#ffffff" - state "heat", label:'${name}', action:"thermostat.cool", backgroundColor:"#ffa81e" - state "cool", label:'${name}', action:"thermostat.auto", backgroundColor:"#269bd2" - state "auto", label:'${name}', action:"thermostat.off", backgroundColor:"#79b821" + state "heat", label:'${name}', action:"thermostat.cool", backgroundColor:"#e86d13" + state "cool", label:'${name}', action:"thermostat.auto", backgroundColor:"#00A0DC" + state "auto", label:'${name}', action:"thermostat.off", backgroundColor:"#00A0DC" } standardTile("fanMode", "device.thermostatFanMode", width: 2, height: 2, inactiveLabel: false, decoration: "flat") { state "fanAuto", label:'${name}', action:"thermostat.fanOn", backgroundColor:"#ffffff" @@ -112,8 +112,8 @@ metadata { } standardTile("operatingState", "device.thermostatOperatingState", width: 2, height: 2) { state "idle", label:'${name}', backgroundColor:"#ffffff" - state "heating", label:'${name}', backgroundColor:"#ffa81e" - state "cooling", label:'${name}', backgroundColor:"#269bd2" + state "heating", label:'${name}', backgroundColor:"#e86d13" + state "cooling", label:'${name}', backgroundColor:"#00A0DC" } main("thermostatMulti") diff --git a/devicetypes/smartthings/testing/simulated-water-sensor.src/simulated-water-sensor.groovy b/devicetypes/smartthings/testing/simulated-water-sensor.src/simulated-water-sensor.groovy index 4998447..b36aa67 100644 --- a/devicetypes/smartthings/testing/simulated-water-sensor.src/simulated-water-sensor.groovy +++ b/devicetypes/smartthings/testing/simulated-water-sensor.src/simulated-water-sensor.groovy @@ -29,7 +29,7 @@ metadata { tiles { standardTile("water", "device.water", width: 2, height: 2) { state "dry", icon:"st.alarm.water.dry", backgroundColor:"#ffffff", action: "wet" - state "wet", icon:"st.alarm.water.wet", backgroundColor:"#53a7c0", action: "dry" + state "wet", icon:"st.alarm.water.wet", backgroundColor:"#00A0DC", action: "dry" } standardTile("wet", "device.water", inactiveLabel: false, decoration: "flat") { state "default", label:'Wet', action:"wet", icon: "st.alarm.water.wet" diff --git a/devicetypes/smartthings/testing/simulated-water-valve.src/simulated-water-valve.groovy b/devicetypes/smartthings/testing/simulated-water-valve.src/simulated-water-valve.groovy index 478d7f6..f767a8c 100644 --- a/devicetypes/smartthings/testing/simulated-water-valve.src/simulated-water-valve.groovy +++ b/devicetypes/smartthings/testing/simulated-water-valve.src/simulated-water-valve.groovy @@ -21,8 +21,8 @@ metadata { // tile definitions tiles { standardTile("contact", "device.contact", width: 2, height: 2, canChangeIcon: true) { - state "closed", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#e86d13" - state "open", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#53a7c0" + state "closed", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#ffffff" + state "open", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#00A0DC" } standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") { state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh" diff --git a/devicetypes/smartthings/tile-ux/tile-basic-carousel.src/tile-basic-carousel.groovy b/devicetypes/smartthings/tile-ux/tile-basic-carousel.src/tile-basic-carousel.groovy index 19a9d91..0af22a2 100644 --- a/devicetypes/smartthings/tile-ux/tile-basic-carousel.src/tile-basic-carousel.groovy +++ b/devicetypes/smartthings/tile-ux/tile-basic-carousel.src/tile-basic-carousel.groovy @@ -41,9 +41,9 @@ metadata { attributeState("default", label:'${currentValue}%', unit:"%") } tileAttribute("device.thermostatOperatingState", key: "OPERATING_STATE") { - attributeState("idle", backgroundColor:"#44b621") - attributeState("heating", backgroundColor:"#ffa81e") - attributeState("cooling", backgroundColor:"#269bd2") + attributeState("idle", backgroundColor:"#ffffff") + attributeState("heating", backgroundColor:"#e86d13") + attributeState("cooling", backgroundColor:"#00a0dc") } tileAttribute("device.thermostatMode", key: "THERMOSTAT_MODE") { attributeState("off", label:'${name}') diff --git a/devicetypes/smartthings/tile-ux/tile-basic-presence.src/tile-basic-presence.groovy b/devicetypes/smartthings/tile-ux/tile-basic-presence.src/tile-basic-presence.groovy index 968fc08..392866c 100644 --- a/devicetypes/smartthings/tile-ux/tile-basic-presence.src/tile-basic-presence.groovy +++ b/devicetypes/smartthings/tile-ux/tile-basic-presence.src/tile-basic-presence.groovy @@ -26,8 +26,8 @@ metadata { tiles(scale: 2) { // You only get a presence tile view when the size is 3x3 otherwise it's a value tile standardTile("presence", "device.presence", width: 3, height: 3, canChangeBackground: true) { - state("present", labelIcon:"st.presence.tile.mobile-present", backgroundColor:"#53a7c0") - state("not present", labelIcon:"st.presence.tile.mobile-not-present", backgroundColor:"#ebeef2") + state("present", labelIcon:"st.presence.tile.mobile-present", backgroundColor:"#00A0DC") + state("not present", labelIcon:"st.presence.tile.mobile-not-present", backgroundColor:"#cccccc") } standardTile("notPresentBtn", "device.fake", width: 3, height: 3, decoration: "flat") { @@ -35,7 +35,7 @@ metadata { } standardTile("presentBtn", "device.fake", width: 3, height: 3, decoration: "flat") { - state("present", label:'present', backgroundColor:"#53a7c0", action:"arrived") + state("present", label:'present', backgroundColor:"#00A0DC", action:"arrived") } main("presence") diff --git a/devicetypes/smartthings/tile-ux/tile-basic-standard.src/tile-basic-standard.groovy b/devicetypes/smartthings/tile-ux/tile-basic-standard.src/tile-basic-standard.groovy index 1f4f029..21fcea6 100644 --- a/devicetypes/smartthings/tile-ux/tile-basic-standard.src/tile-basic-standard.groovy +++ b/devicetypes/smartthings/tile-ux/tile-basic-standard.src/tile-basic-standard.groovy @@ -24,19 +24,19 @@ metadata { // standard tile with actions standardTile("actionRings", "device.switch", width: 2, height: 2, canChangeIcon: true) { state "off", label: '${currentValue}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" - state "on", label: '${currentValue}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" + state "on", label: '${currentValue}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC" } // standard flat tile with actions standardTile("actionFlat", "device.switch", width: 2, height: 2, canChangeIcon: true, decoration: "flat") { state "off", label: '${currentValue}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" - state "on", label: '${currentValue}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" + state "on", label: '${currentValue}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC" } // standard flat tile without actions standardTile("noActionFlat", "device.switch", width: 2, height: 2, canChangeIcon: true) { state "off", label: '${currentValue}',icon: "st.switches.switch.off", backgroundColor: "#ffffff" - state "on", label: '${currentValue}', icon: "st.switches.switch.on", backgroundColor: "#79b821" + state "on", label: '${currentValue}', icon: "st.switches.switch.on", backgroundColor: "#00A0DC" } // standard flat tile with only a label diff --git a/devicetypes/smartthings/tile-ux/tile-multiattribute-generic.src/tile-multiattribute-generic.groovy b/devicetypes/smartthings/tile-ux/tile-multiattribute-generic.src/tile-multiattribute-generic.groovy index d535647..9353c00 100644 --- a/devicetypes/smartthings/tile-ux/tile-multiattribute-generic.src/tile-multiattribute-generic.groovy +++ b/devicetypes/smartthings/tile-ux/tile-multiattribute-generic.src/tile-multiattribute-generic.groovy @@ -25,7 +25,7 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"basicTile", type:"generic", width:6, height:4) { tileAttribute("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" @@ -33,7 +33,7 @@ metadata { } multiAttributeTile(name:"sliderTile", type:"generic", width:6, height:4) { tileAttribute("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', backgroundColor:"#79b821", nextState:"turningOff" + attributeState "on", label:'${name}', backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "off", label:'${name}', backgroundColor:"#ffffff", nextState:"turningOn" attributeState "turningOn", label:'${name}', backgroundColor:"#79b821", nextState:"turningOff" attributeState "turningOff", label:'${name}', backgroundColor:"#ffffff", nextState:"turningOn" @@ -57,7 +57,7 @@ metadata { ] } tileAttribute("device.switch", key: "SECONDARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "off", label:'${name}', action:"switch.on", backgroundColor:"#ffffff", nextState:"turningOn" attributeState "turningOn", label:'…', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" attributeState "turningOff", label:'…', action:"switch.on", backgroundColor:"#ffffff", nextState:"turningOn" diff --git a/devicetypes/smartthings/tile-ux/tile-multiattribute-lighting.src/tile-multiattribute-lighting.groovy b/devicetypes/smartthings/tile-ux/tile-multiattribute-lighting.src/tile-multiattribute-lighting.groovy index 7ffaabc..283f5a5 100644 --- a/devicetypes/smartthings/tile-ux/tile-multiattribute-lighting.src/tile-multiattribute-lighting.groovy +++ b/devicetypes/smartthings/tile-ux/tile-multiattribute-lighting.src/tile-multiattribute-lighting.groovy @@ -33,9 +33,9 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true) { tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" } tileAttribute ("device.power", key: "SECONDARY_CONTROL") { @@ -51,9 +51,9 @@ metadata { multiAttributeTile(name:"switchNoPower", type: "lighting", width: 6, height: 4, canChangeIcon: true) { tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" } tileAttribute ("device.level", key: "SLIDER_CONTROL") { @@ -66,9 +66,9 @@ metadata { multiAttributeTile(name:"switchNoSlider", type: "lighting", width: 6, height: 4, canChangeIcon: true) { tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" } tileAttribute ("device.power", key: "SECONDARY_CONTROL") { @@ -81,9 +81,9 @@ metadata { multiAttributeTile(name:"switchNoSliderOrColor", type: "lighting", width: 6, height: 4, canChangeIcon: true) { tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" } tileAttribute ("device.power", key: "SECONDARY_CONTROL") { diff --git a/devicetypes/smartthings/tile-ux/tile-multiattribute-thermostat.src/tile-multiattribute-thermostat.groovy b/devicetypes/smartthings/tile-ux/tile-multiattribute-thermostat.src/tile-multiattribute-thermostat.groovy index 6fb57bd..a784ac5 100644 --- a/devicetypes/smartthings/tile-ux/tile-multiattribute-thermostat.src/tile-multiattribute-thermostat.groovy +++ b/devicetypes/smartthings/tile-ux/tile-multiattribute-thermostat.src/tile-multiattribute-thermostat.groovy @@ -42,9 +42,9 @@ metadata { attributeState("humidity", label:'${currentValue}%', unit:"%", defaultState: true) } tileAttribute("device.thermostatOperatingState", key: "OPERATING_STATE") { - attributeState("idle", backgroundColor:"#44b621") - attributeState("heating", backgroundColor:"#ffa81e") - attributeState("cooling", backgroundColor:"#269bd2") + attributeState("idle", backgroundColor:"#00A0DC") + attributeState("heating", backgroundColor:"#e86d13") + attributeState("cooling", backgroundColor:"#00A0DC") } tileAttribute("device.thermostatMode", key: "THERMOSTAT_MODE") { attributeState("off", label:'${name}') @@ -69,9 +69,9 @@ metadata { attributeState("VALUE_DOWN", action: "tempDown") } tileAttribute("device.thermostatOperatingState", key: "OPERATING_STATE") { - attributeState("idle", backgroundColor:"#44b621") - attributeState("heating", backgroundColor:"#ffa81e") - attributeState("cooling", backgroundColor:"#269bd2") + attributeState("idle", backgroundColor:"#00A0DC") + attributeState("heating", backgroundColor:"#e86d13") + attributeState("cooling", backgroundColor:"#00A0DC") } tileAttribute("device.thermostatMode", key: "THERMOSTAT_MODE") { attributeState("off", label:'${name}') @@ -148,9 +148,9 @@ metadata { standardTile("mode", "device.thermostatMode", width: 2, height: 2, inactiveLabel: false, decoration: "flat") { state "off", label:'${name}', action:"thermostat.heat", backgroundColor:"#ffffff" - state "heat", label:'${name}', action:"thermostat.cool", backgroundColor:"#ffa81e" - state "cool", label:'${name}', action:"thermostat.auto", backgroundColor:"#269bd2" - state "auto", label:'${name}', action:"thermostat.off", backgroundColor:"#79b821" + state "heat", label:'${name}', action:"thermostat.cool", backgroundColor:"#e86d13" + state "cool", label:'${name}', action:"thermostat.auto", backgroundColor:"#00A0DC" + state "auto", label:'${name}', action:"thermostat.off", backgroundColor:"#00A0DC" } standardTile("fanMode", "device.thermostatFanMode", width: 2, height: 2, inactiveLabel: false, decoration: "flat") { state "fanAuto", label:'${name}', action:"thermostat.fanOn", backgroundColor:"#ffffff" @@ -159,8 +159,8 @@ metadata { } standardTile("operatingState", "device.thermostatOperatingState", width: 2, height: 2) { state "idle", label:'${name}', backgroundColor:"#ffffff" - state "heating", label:'${name}', backgroundColor:"#ffa81e" - state "cooling", label:'${name}', backgroundColor:"#269bd2" + state "heating", label:'${name}', backgroundColor:"#e86d13" + state "cooling", label:'${name}', backgroundColor:"#00A0DC" } diff --git a/devicetypes/smartthings/tile-ux/tile-multiattribute-videoplayer.src/tile-multiattribute-videoplayer.groovy b/devicetypes/smartthings/tile-ux/tile-multiattribute-videoplayer.src/tile-multiattribute-videoplayer.groovy index 792b458..c6dc80d 100644 --- a/devicetypes/smartthings/tile-ux/tile-multiattribute-videoplayer.src/tile-multiattribute-videoplayer.groovy +++ b/devicetypes/smartthings/tile-ux/tile-multiattribute-videoplayer.src/tile-multiattribute-videoplayer.groovy @@ -34,10 +34,10 @@ metadata { tiles(scale: 2) { multiAttributeTile(name: "videoPlayer", type: "videoPlayer", width: 6, height: 4) { tileAttribute("device.switch", key: "CAMERA_STATUS") { - attributeState("on", label: "Active", icon: "st.camera.dlink-indoor", action: "switch.off", backgroundColor: "#79b821", defaultState: true) + attributeState("on", label: "Active", icon: "st.camera.dlink-indoor", action: "switch.off", backgroundColor: "#00A0DC", defaultState: true) attributeState("off", label: "Inactive", icon: "st.camera.dlink-indoor", action: "switch.on", backgroundColor: "#ffffff") - attributeState("restarting", label: "Connecting", icon: "st.camera.dlink-indoor", backgroundColor: "#53a7c0") - attributeState("unavailable", label: "Unavailable", icon: "st.camera.dlink-indoor", action: "refresh.refresh", backgroundColor: "#F22000") + attributeState("restarting", label: "Connecting", icon: "st.camera.dlink-indoor", backgroundColor: "#00A0DC") + attributeState("unavailable", label: "Unavailable", icon: "st.camera.dlink-indoor", action: "refresh.refresh", backgroundColor: "#cccccc") } tileAttribute("device.errorMessage", key: "CAMERA_ERROR_MESSAGE") { @@ -45,10 +45,10 @@ metadata { } tileAttribute("device.camera", key: "PRIMARY_CONTROL") { - attributeState("on", label: "Active", icon: "st.camera.dlink-indoor", backgroundColor: "#79b821", defaultState: true) + attributeState("on", label: "Active", icon: "st.camera.dlink-indoor", backgroundColor: "#00A0DC", defaultState: true) attributeState("off", label: "Inactive", icon: "st.camera.dlink-indoor", backgroundColor: "#ffffff") - attributeState("restarting", label: "Connecting", icon: "st.camera.dlink-indoor", backgroundColor: "#53a7c0") - attributeState("unavailable", label: "Unavailable", icon: "st.camera.dlink-indoor", backgroundColor: "#F22000") + attributeState("restarting", label: "Connecting", icon: "st.camera.dlink-indoor", backgroundColor: "#00A0DC") + attributeState("unavailable", label: "Unavailable", icon: "st.camera.dlink-indoor", backgroundColor: "#cccccc") } tileAttribute("device.startLive", key: "START_LIVE") { @@ -72,10 +72,10 @@ metadata { multiAttributeTile(name: "videoPlayerMin", type: "videoPlayer", width: 6, height: 4) { tileAttribute("device.switch", key: "CAMERA_STATUS") { - attributeState("on", label: "Active", icon: "st.camera.dlink-indoor", action: "switch.off", backgroundColor: "#79b821", defaultState: true) + attributeState("on", label: "Active", icon: "st.camera.dlink-indoor", action: "switch.off", backgroundColor: "#00A0DC", defaultState: true) attributeState("off", label: "Inactive", icon: "st.camera.dlink-indoor", action: "switch.on", backgroundColor: "#ffffff") - attributeState("restarting", label: "Connecting", icon: "st.camera.dlink-indoor", backgroundColor: "#53a7c0") - attributeState("unavailable", label: "Unavailable", icon: "st.camera.dlink-indoor", action: "refresh.refresh", backgroundColor: "#F22000") + attributeState("restarting", label: "Connecting", icon: "st.camera.dlink-indoor", backgroundColor: "#00A0DC") + attributeState("unavailable", label: "Unavailable", icon: "st.camera.dlink-indoor", action: "refresh.refresh", backgroundColor: "#cccccc") } tileAttribute("device.errorMessage", key: "CAMERA_ERROR_MESSAGE") { @@ -83,10 +83,10 @@ metadata { } tileAttribute("device.camera", key: "PRIMARY_CONTROL") { - attributeState("on", label: "Active", icon: "st.camera.dlink-indoor", backgroundColor: "#79b821", defaultState: true) + attributeState("on", label: "Active", icon: "st.camera.dlink-indoor", backgroundColor: "#00A0DC", defaultState: true) attributeState("off", label: "Inactive", icon: "st.camera.dlink-indoor", backgroundColor: "#ffffff") - attributeState("restarting", label: "Connecting", icon: "st.camera.dlink-indoor", backgroundColor: "#53a7c0") - attributeState("unavailable", label: "Unavailable", icon: "st.camera.dlink-indoor", backgroundColor: "#F22000") + attributeState("restarting", label: "Connecting", icon: "st.camera.dlink-indoor", backgroundColor: "#00A0DC") + attributeState("unavailable", label: "Unavailable", icon: "st.camera.dlink-indoor", backgroundColor: "#cccccc") } tileAttribute("device.startLive", key: "START_LIVE") { diff --git a/devicetypes/smartthings/tyco-door-window-sensor.src/tyco-door-window-sensor.groovy b/devicetypes/smartthings/tyco-door-window-sensor.src/tyco-door-window-sensor.groovy index 95238d4..305d3fe 100644 --- a/devicetypes/smartthings/tyco-door-window-sensor.src/tyco-door-window-sensor.groovy +++ b/devicetypes/smartthings/tyco-door-window-sensor.src/tyco-door-window-sensor.groovy @@ -41,8 +41,8 @@ metadata { 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") + state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#e86d13") + state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#00A0DC") } valueTile("temperature", "device.temperature", inactiveLabel: false) { diff --git a/devicetypes/smartthings/unknown.src/unknown.groovy b/devicetypes/smartthings/unknown.src/unknown.groovy index e084bb1..12cee41 100644 --- a/devicetypes/smartthings/unknown.src/unknown.groovy +++ b/devicetypes/smartthings/unknown.src/unknown.groovy @@ -23,7 +23,7 @@ metadata { // UI tile definitions tiles { standardTile("unknown", "device.unknown", width: 2, height: 2) { - state(name:"default", icon:"st.unknown.unknown.unknown", backgroundColor:"#767676", label: "Unknown") + state(name:"default", icon:"st.unknown.unknown.unknown", backgroundColor:"#ffffff", label: "Unknown") } main "unknown" diff --git a/devicetypes/smartthings/wemo-bulb.src/wemo-bulb.groovy b/devicetypes/smartthings/wemo-bulb.src/wemo-bulb.groovy index 243dafb..8f98b02 100644 --- a/devicetypes/smartthings/wemo-bulb.src/wemo-bulb.groovy +++ b/devicetypes/smartthings/wemo-bulb.src/wemo-bulb.groovy @@ -43,9 +43,9 @@ metadata { // UI tile definitions tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { - state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" + state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff" state "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" - state "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" + state "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff" state "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" } standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") { diff --git a/devicetypes/smartthings/wemo-light-switch.src/wemo-light-switch.groovy b/devicetypes/smartthings/wemo-light-switch.src/wemo-light-switch.groovy index 94e2715..b90a577 100644 --- a/devicetypes/smartthings/wemo-light-switch.src/wemo-light-switch.groovy +++ b/devicetypes/smartthings/wemo-light-switch.src/wemo-light-switch.groovy @@ -52,11 +52,11 @@ metadata { } standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { - state "on", label:'${name}', action:"switch.off", icon:"st.Home.home30", backgroundColor:"#79b821", nextState:"turningOff" + state "on", label:'${name}', action:"switch.off", icon:"st.Home.home30", backgroundColor:"#00A0DC", nextState:"turningOff" state "off", label:'${name}', action:"switch.on", icon:"st.Home.home30", backgroundColor:"#ffffff", nextState:"turningOn" - state "turningOn", label:'${name}', action:"switch.off", icon:"st.Home.home30", backgroundColor:"#79b821", nextState:"turningOff" + state "turningOn", label:'${name}', action:"switch.off", icon:"st.Home.home30", backgroundColor:"#00A0DC", nextState:"turningOff" state "turningOff", label:'${name}', action:"switch.on", icon:"st.Home.home30", backgroundColor:"#ffffff", nextState:"turningOn" - state "offline", label:'${name}', icon:"st.Home.home30", backgroundColor:"#ff0000" + state "offline", label:'${name}', icon:"st.Home.home30", backgroundColor:"#cccccc" } standardTile("refresh", "device.switch", inactiveLabel: false, height: 2, width: 2, decoration: "flat") { @@ -86,7 +86,7 @@ def parse(String description) { def bodyString = msg.body if (bodyString) { unschedule("setOffline") - def body = new XmlSlurper().parseText(bodyString) + def body = new XmlSlurper().parseText(bodyString.replaceAll("[^\\x20-\\x7e]", "")) if (body?.property?.TimeSyncRequest?.text()) { log.trace "Got TimeSyncRequest" diff --git a/devicetypes/smartthings/wemo-motion.src/wemo-motion.groovy b/devicetypes/smartthings/wemo-motion.src/wemo-motion.groovy index b7fbee1..fe844f2 100644 --- a/devicetypes/smartthings/wemo-motion.src/wemo-motion.groovy +++ b/devicetypes/smartthings/wemo-motion.src/wemo-motion.groovy @@ -36,9 +36,9 @@ tiles(scale: 2) { multiAttributeTile(name:"rich-control", type: "motion", canChangeIcon: true){ tileAttribute ("device.motion", key: "PRIMARY_CONTROL") { - attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0" - attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff" - attributeState "offline", label:'${name}', icon:"st.motion.motion.active", backgroundColor:"#ff0000" + attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC" + attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc" + attributeState "offline", label:'${name}', icon:"st.motion.motion.active", backgroundColor:"#cccccc" } tileAttribute ("currentIP", key: "SECONDARY_CONTROL") { attributeState "currentIP", label: '' @@ -78,7 +78,7 @@ def parse(String description) { def bodyString = msg.body if (bodyString) { unschedule("setOffline") - def body = new XmlSlurper().parseText(bodyString) + def body = new XmlSlurper().parseText(bodyString.replaceAll("[^\\x20-\\x7e]", "")) if (body?.property?.TimeSyncRequest?.text()) { log.trace "Got TimeSyncRequest" result << timeSyncResponse() diff --git a/devicetypes/smartthings/wemo-switch.src/wemo-switch.groovy b/devicetypes/smartthings/wemo-switch.src/wemo-switch.groovy index 6ac3939..fcda9ec 100644 --- a/devicetypes/smartthings/wemo-switch.src/wemo-switch.groovy +++ b/devicetypes/smartthings/wemo-switch.src/wemo-switch.groovy @@ -84,7 +84,7 @@ def parse(String description) { def bodyString = msg.body if (bodyString) { unschedule("setOffline") - def body = new XmlSlurper().parseText(bodyString) + def body = new XmlSlurper().parseText(bodyString.replaceAll("[^\\x20-\\x7e]", "")) if (body?.property?.TimeSyncRequest?.text()) { log.trace "Got TimeSyncRequest" result << timeSyncResponse() @@ -208,7 +208,7 @@ def subscribe(ip, port) { def existingIp = getDataValue("ip") def existingPort = getDataValue("port") if (ip && ip != existingIp) { - log.debug "Updating ip from $existingIp to $ip" + log.debug "Updating ip from $existingIp to $ip" updateDataValue("ip", ip) def ipvalue = convertHexToIP(getDataValue("ip")) sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP changed to ${ipvalue}") @@ -291,4 +291,4 @@ User-Agent: CyberGarage-HTTP/1.0 """, physicalgraph.device.Protocol.LAN) -} \ No newline at end of file +} diff --git a/devicetypes/smartthings/zigbee-button.src/zigbee-button.groovy b/devicetypes/smartthings/zigbee-button.src/zigbee-button.groovy index 3f68e62..f3e04f1 100644 --- a/devicetypes/smartthings/zigbee-button.src/zigbee-button.groovy +++ b/devicetypes/smartthings/zigbee-button.src/zigbee-button.groovy @@ -13,6 +13,7 @@ * for the specific language governing permissions and limitations under the License. * */ +import physicalgraph.zigbee.zcl.DataType metadata { definition (name: "ZigBee Button", namespace: "smartthings", author: "Mitch Pond") { @@ -28,8 +29,8 @@ metadata { fingerprint inClusters: "0000, 0001, 0003, 0020, 0402, 0B05", outClusters: "0003, 0006, 0008, 0019", manufacturer: "OSRAM", model: "LIGHTIFY Dimming Switch", deviceJoinName: "OSRAM LIGHTIFY Dimming Switch" //fingerprint inClusters: "0000, 0001, 0003, 0020, 0500", outClusters: "0003,0019", manufacturer: "CentraLite", model: "3455-L", deviceJoinName: "Iris Care Pendant" - //fingerprint inClusters: "0000, 0001, 0003, 0007, 0020, 0402, 0B05", outClusters: "0003, 0006, 0019", manufacturer: "CentraLite", model: "3460-L", deviceJoinName: "Iris Smart Button" - //fingerprint inClusters: "0000, 0001, 0003, 0007, 0020, 0B05", outClusters: "0003, 0006, 0019", manufacturer: "CentraLite", model:"3450-L", deviceJoinName: "Iris KeyFob" + fingerprint inClusters: "0000, 0001, 0003, 0007, 0020, 0402, 0B05", outClusters: "0003, 0006, 0019", manufacturer: "CentraLite", model: "3460-L", deviceJoinName: "Iris Smart Button" + fingerprint inClusters: "0000, 0001, 0003, 0007, 0020, 0B05", outClusters: "0003, 0006, 0019", manufacturer: "CentraLite", model:"3450-L", deviceJoinName: "Iris KeyFob" } simulator {} @@ -43,7 +44,7 @@ metadata { tiles { standardTile("button", "device.button", width: 2, height: 2) { state "default", label: "", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#ffffff" - state "button 1 pushed", label: "pushed #1", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#79b821" + state "button 1 pushed", label: "pushed #1", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#00A0DC" } valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false) { @@ -82,7 +83,7 @@ def parse(String description) { def result = event ? createEvent(event) : [] if (description?.startsWith('enroll request')) { - List cmds = enrollResponse() + List cmds = zigbee.enrollResponse() result = cmds?.collect { new physicalgraph.device.HubAction(it) } } return result @@ -117,15 +118,38 @@ private Map getBatteryResult(rawValue) { private Map parseNonIasButtonMessage(Map descMap){ def buttonState = "" def buttonNumber = 0 - if (((device.getDataValue("model") == "3460-L") || (device.getDataValue("model") == "3450-L")) - &&(descMap.clusterInt == 0x0006)) { - if (descMap.command == "01") { + if ((device.getDataValue("model") == "3460-L") &&(descMap.clusterInt == 0x0006)) { + if (descMap.commandInt == 1) { getButtonResult("press") } - else if (descMap.command == "00") { + else if (descMap.commandInt == 0) { getButtonResult("release") } } + else if ((device.getDataValue("model") == "3450-L") && (descMap.clusterInt == 0x0006)) { + if (descMap.commandInt == 1) { + getButtonResult("press") + } + else if (descMap.commandInt == 0) { + def button = 1 + switch(descMap.sourceEndpoint) { + case "01": + button = 4 + break + case "02": + button = 3 + break + case "03": + button = 1 + break + case "04": + button = 2 + break + } + + getButtonResult("release", button) + } + } else if (descMap.clusterInt == 0x0006) { buttonState = "pushed" if (descMap.command == "01") { @@ -160,7 +184,7 @@ private Map parseNonIasButtonMessage(Map descMap){ def refresh() { log.debug "Refreshing Battery" - return zigbee.readAttribute(0x0001, 0x20) + + return zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x20) + zigbee.enrollResponse() } @@ -177,9 +201,9 @@ def configure() { } return zigbee.onOffConfig() + zigbee.levelConfig() + - zigbee.configureReporting(0x0001, 0x20, 0x20, 30, 21600, 0x01) + + zigbee.configureReporting(zigbee.POWER_CONFIGURATION_CLUSTER, 0x20, DataType.UINT8, 30, 21600, 0x01) + zigbee.enrollResponse() + - zigbee.readAttribute(0x0001, 0x20) + + zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x20) + cmds } diff --git a/devicetypes/smartthings/zigbee-dimmer-power.src/README.md b/devicetypes/smartthings/zigbee-dimmer-power.src/README.md index 130f20c..196101f 100644 --- a/devicetypes/smartthings/zigbee-dimmer-power.src/README.md +++ b/devicetypes/smartthings/zigbee-dimmer-power.src/README.md @@ -23,6 +23,7 @@ Works with: * **Switch** - can detect state (possible values: on/off) * **Switch Level** - represents current light level, usually 0-100 in percent * **Health Check** - indicates ability to get device health notifications +* **Light** - indicates that the device belongs to Light category. ## Device Health diff --git a/devicetypes/smartthings/zigbee-dimmer-power.src/zigbee-dimmer-power.groovy b/devicetypes/smartthings/zigbee-dimmer-power.src/zigbee-dimmer-power.groovy index 4bef6a9..ceea649 100644 --- a/devicetypes/smartthings/zigbee-dimmer-power.src/zigbee-dimmer-power.groovy +++ b/devicetypes/smartthings/zigbee-dimmer-power.src/zigbee-dimmer-power.groovy @@ -22,6 +22,7 @@ metadata { capability "Switch" capability "Switch Level" capability "Health Check" + capability "Light" fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0B04" fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0702" @@ -33,9 +34,9 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" } tileAttribute ("device.level", key: "SLIDER_CONTROL") { @@ -97,7 +98,7 @@ def on() { } def setLevel(value) { - zigbee.setLevel(value) + zigbee.setLevel(value) + (value?.toInteger() > 0 ? zigbee.on() : []) } /** diff --git a/devicetypes/smartthings/zigbee-dimmer.src/zigbee-dimmer.groovy b/devicetypes/smartthings/zigbee-dimmer.src/zigbee-dimmer.groovy index 8b41e2e..55b22f2 100644 --- a/devicetypes/smartthings/zigbee-dimmer.src/zigbee-dimmer.groovy +++ b/devicetypes/smartthings/zigbee-dimmer.src/zigbee-dimmer.groovy @@ -20,6 +20,7 @@ metadata { capability "Switch" capability "Switch Level" capability "Health Check" + capability "Light" fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008" @@ -28,14 +29,18 @@ metadata { fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0B05", outClusters: "0019", manufacturer: "OSRAM SYLVANIA", model: "iQBR30", deviceJoinName: "Sylvania Ultra iQ" fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY PAR38 ON/OFF/DIM", deviceJoinName: "SYLVANIA Smart PAR38 Soft White" fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY BR ON/OFF/DIM", deviceJoinName: "SYLVANIA Smart BR30 Soft White" + fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0702, 0B05", outClusters: "0019", manufacturer: "sengled", model: "E11-G13", deviceJoinName: "Sengled Element Classic" + fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008", outClusters: "0003, 0006, 0008, 0019, 0406", manufacturer: "Leviton", model: "DL6HD", deviceJoinName: "Leviton Dimmer Switch" + fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008", outClusters: "0003, 0006, 0008, 0019, 0406", manufacturer: "Leviton", model: "DL3HL", deviceJoinName: "Leviton Lumina RF Plug-In Dimmer" + fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008", outClusters: "0003, 0006, 0008, 0019, 0406", manufacturer: "Leviton", model: "DL1KD", deviceJoinName: "Leviton Lumina RF Dimmer Switch" } tiles(scale: 2) { multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn" } tileAttribute ("device.level", key: "SLIDER_CONTROL") { @@ -89,7 +94,13 @@ def on() { } def setLevel(value) { - zigbee.setLevel(value) + def additionalCmds = [] + if (device.getDataValue("model") == "iQBR30" && value.toInteger() > 0) { // Handle iQ bulb not following spec + additionalCmds = zigbee.on() + } else if (device.getDataValue("manufacturer") == "MRVL") { // Handle marvel stack not reporting + additionalCmds = refresh() + } + zigbee.setLevel(value) + additionalCmds } /** * PING is used by Device-Watch in attempt to reach the Device @@ -99,7 +110,15 @@ def ping() { } def refresh() { - zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh() +} + +def installed() { + if (((device.getDataValue("manufacturer") == "MRVL") && (device.getDataValue("model") == "MZ100")) || (device.getDataValue("manufacturer") == "OSRAM SYLVANIA") || (device.getDataValue("manufacturer") == "OSRAM")) { + if ((device.currentState("level")?.value == null) || (device.currentState("level")?.value == 0)) { + sendEvent(name: "level", value: 100) + } + } } def configure() { @@ -109,5 +128,5 @@ def configure() { sendEvent(name: "checkInterval", value: 2 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) // OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity - zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + refresh() + zigbee.onOffConfig(0, 300) + zigbee.levelConfig() } diff --git a/devicetypes/smartthings/zigbee-lock.src/zigbee-lock.groovy b/devicetypes/smartthings/zigbee-lock.src/zigbee-lock.groovy index 41de4e8..fb31a6b 100644 --- a/devicetypes/smartthings/zigbee-lock.src/zigbee-lock.groovy +++ b/devicetypes/smartthings/zigbee-lock.src/zigbee-lock.groovy @@ -13,6 +13,8 @@ * for the specific language governing permissions and limitations under the License. * */ +import physicalgraph.zigbee.zcl.DataType + metadata { definition (name: "ZigBee Lock", namespace: "smartthings", author: "SmartThings") { @@ -37,10 +39,10 @@ tiles(scale: 2) { multiAttributeTile(name:"toggle", type:"generic", width:6, height:4){ tileAttribute ("device.lock", key:"PRIMARY_CONTROL") { - attributeState "locked", label:'locked', action:"lock.unlock", icon:"st.locks.lock.locked", backgroundColor:"#79b821", nextState:"unlocking" + attributeState "locked", label:'locked', action:"lock.unlock", icon:"st.locks.lock.locked", backgroundColor:"#00A0DC", nextState:"unlocking" attributeState "unlocked", label:'unlocked', action:"lock.lock", icon:"st.locks.lock.unlocked", backgroundColor:"#ffffff", nextState:"locking" attributeState "unknown", label:"unknown", action:"lock.lock", icon:"st.locks.lock.unknown", backgroundColor:"#ffffff", nextState:"locking" - attributeState "locking", label:'locking', icon:"st.locks.lock.locked", backgroundColor:"#79b821" + attributeState "locking", label:'locking', icon:"st.locks.lock.locked", backgroundColor:"#00A0DC" attributeState "unlocking", label:'unlocking', icon:"st.locks.lock.unlocked", backgroundColor:"#ffffff" } } @@ -71,9 +73,6 @@ private getDOORLOCK_CMD_UNLOCK_DOOR() { 0x01 } private getDOORLOCK_ATTR_LOCKSTATE() { 0x0000 } private getPOWER_ATTR_BATTERY_PERCENTAGE_REMAINING() { 0x0021 } -private getTYPE_U8() { 0x20 } -private getTYPE_ENUM8() { 0x30 } - // Public methods def installed() { log.trace "installed()" @@ -86,9 +85,9 @@ def uninstalled() { def configure() { def cmds = zigbee.configureReporting(CLUSTER_DOORLOCK, DOORLOCK_ATTR_LOCKSTATE, - TYPE_ENUM8, 0, 3600, null) + + DataType.ENUM8, 0, 3600, null) + zigbee.configureReporting(CLUSTER_POWER, POWER_ATTR_BATTERY_PERCENTAGE_REMAINING, - TYPE_U8, 600, 21600, 0x01) + DataType.UINT8, 600, 21600, 0x01) log.info "configure() --- cmds: $cmds" return refresh() + cmds // send refresh cmds as part of config } diff --git a/devicetypes/smartthings/zigbee-rgb-bulb.src/.st-ignore b/devicetypes/smartthings/zigbee-rgb-bulb.src/.st-ignore new file mode 100644 index 0000000..f78b46e --- /dev/null +++ b/devicetypes/smartthings/zigbee-rgb-bulb.src/.st-ignore @@ -0,0 +1,2 @@ +.st-ignore +README.md diff --git a/devicetypes/smartthings/zigbee-rgb-bulb.src/README.md b/devicetypes/smartthings/zigbee-rgb-bulb.src/README.md new file mode 100644 index 0000000..f59f26c --- /dev/null +++ b/devicetypes/smartthings/zigbee-rgb-bulb.src/README.md @@ -0,0 +1,39 @@ +# ZigBee RGB Bulb + +Cloud Execution + +Works with: + +* [OSRAM LIGHTIFY Gardenspot mini RGB](https://www.smartthings.com/works-with-smartthings/lighting-and-switches/osram-lightify-gardenspot-rgb) + +## Table of contents + +* [Capabilities](#capabilities) +* [Health](#device-health) +* [Battery](#battery-specification) + +## Capabilities + +* **Actuator** - represents that a Device has commands +* **Color Control** - It represents that the color attributes of a device can be controlled (hue, saturation, color value). +* **Configuration** - _configure()_ command called when device is installed or device preferences updated. +* **Polling** - It represents that a device can be polled. +* **Refresh** - _refresh()_ command for status updates +* **Switch** - can detect state (possible values: on/off) +* **Switch Level** - represents current light level, usually 0-100 in percent +* **Health Check** - indicates ability to get device health notifications +* **Light** - Indicates that the device belongs to light category. + +## Device Health + +Zigbee RGB Bulb with reporting interval of 5 mins. +SmartThings platform will ping the device after `checkInterval` seconds of inactivity in last attempt to reach the device before marking it `OFFLINE` + +*__12min__ checkInterval + +## Troubleshooting + +If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range. +Pairing needs to be tried again by placing the device closer to the hub. +Other troubleshooting tips are listed as follows: +* [OSRAM LIGHTIFY Gardenspot mini RGB Troubleshooting](https://support.smartthings.com/hc/en-us/articles/214191863) \ No newline at end of file diff --git a/devicetypes/smartthings/zigbee-rgb-bulb.src/zigbee-rgb-bulb.groovy b/devicetypes/smartthings/zigbee-rgb-bulb.src/zigbee-rgb-bulb.groovy index 64de2fb..918483d 100644 --- a/devicetypes/smartthings/zigbee-rgb-bulb.src/zigbee-rgb-bulb.groovy +++ b/devicetypes/smartthings/zigbee-rgb-bulb.src/zigbee-rgb-bulb.groovy @@ -15,6 +15,7 @@ * * This DTH should serve as the generic DTH to handle RGB ZigBee HA devices (For color bulbs with no color temperature) */ +import physicalgraph.zigbee.zcl.DataType metadata { definition (name: "ZigBee RGB Bulb", namespace: "smartthings", author: "SmartThings") { @@ -27,6 +28,7 @@ metadata { capability "Switch" capability "Switch Level" capability "Health Check" + capability "Light" fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0300,0B04,FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "Gardenspot RGB", deviceJoinName: "SYLVANIA Smart Gardenspot mini RGB" fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0300,0B04,FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY Gardenspot RGB", deviceJoinName: "SYLVANIA Smart Gardenspot mini RGB" @@ -36,9 +38,9 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" } tileAttribute ("device.level", key: "SLIDER_CONTROL") { @@ -121,7 +123,7 @@ def ping() { } def refresh() { - zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION) + zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, 0x20, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, 0x20, 1, 3600, 0x01) + zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION) + zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, DataType.UINT8, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, DataType.UINT8, 1, 3600, 0x01) } def configure() { @@ -131,7 +133,7 @@ def configure() { sendEvent(name: "checkInterval", value: 3 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) // OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity - zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, 0x20, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, 0x20, 1, 3600, 0x01) + zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION) + zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, DataType.UINT8, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, DataType.UINT8, 1, 3600, 0x01) + zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION) } def setLevel(value) { @@ -151,4 +153,12 @@ def setHue(value) { def setSaturation(value) { def scaledSatValue = zigbee.convertToHexString(Math.round(value * 0xfe / 100.0), 2) zigbee.command(COLOR_CONTROL_CLUSTER, SATURATION_COMMAND, scaledSatValue, "0500") + "delay 1000" + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION) +} + +def installed() { + if (((device.getDataValue("manufacturer") == "MRVL") && (device.getDataValue("model") == "MZ100")) || (device.getDataValue("manufacturer") == "OSRAM SYLVANIA") || (device.getDataValue("manufacturer") == "OSRAM")) { + if ((device.currentState("level")?.value == null) || (device.currentState("level")?.value == 0)) { + sendEvent(name: "level", value: 100) + } + } } \ No newline at end of file diff --git a/devicetypes/smartthings/zigbee-rgbw-bulb.src/README.md b/devicetypes/smartthings/zigbee-rgbw-bulb.src/README.md index 0e413e5..e704056 100644 --- a/devicetypes/smartthings/zigbee-rgbw-bulb.src/README.md +++ b/devicetypes/smartthings/zigbee-rgbw-bulb.src/README.md @@ -4,7 +4,8 @@ Cloud Execution Works with: -* [OSRAM LIGHTIFY LED RGBW Bulb](https://support.smartthings.com/hc/en-us/articles/207728173-OSRAM-LIGHTIFY-LED-Smart-Connected-Light-A19-RGBW) +* [OSRAM LIGHTIFY LED Smart Connected Light A19 RGBW](https://support.smartthings.com/hc/en-us/articles/207728173-OSRAM-LIGHTIFY-LED-Smart-Connected-Light-A19-RGBW) +* [OSRAM LIGHTIFY Flex RGBW strips](https://www.smartthings.com/works-with-smartthings/lighting-and-switches/osram-lightify-flex-rgbw-strips) ## Table of contents @@ -38,4 +39,5 @@ If the device doesn't pair when trying from the SmartThings mobile app, it is po Pairing needs to be tried again by placing the device closer to the hub. It may also happen that you need to reset the device. Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link: -* [Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/207728173-OSRAM-LIGHTIFY-LED-Smart-Connected-Light-A19-RGBW) \ No newline at end of file +* [OSRAM LIGHTIFY LED Smart Connected Light A19 RGBW Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/207728173-OSRAM-LIGHTIFY-LED-Smart-Connected-Light-A19-RGBW) +* [OSRAM LIGHTIFY Flex RGBW strips Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/214191863) \ No newline at end of file diff --git a/devicetypes/smartthings/zigbee-rgbw-bulb.src/zigbee-rgbw-bulb.groovy b/devicetypes/smartthings/zigbee-rgbw-bulb.src/zigbee-rgbw-bulb.groovy index 87360fe..a3094dd 100644 --- a/devicetypes/smartthings/zigbee-rgbw-bulb.src/zigbee-rgbw-bulb.groovy +++ b/devicetypes/smartthings/zigbee-rgbw-bulb.src/zigbee-rgbw-bulb.groovy @@ -15,6 +15,7 @@ * * This DTH should serve as the generic DTH to handle RGBW ZigBee HA devices */ +import physicalgraph.zigbee.zcl.DataType metadata { definition (name: "ZigBee RGBW Bulb", namespace: "smartthings", author: "SmartThings") { @@ -28,6 +29,7 @@ metadata { capability "Switch" capability "Switch Level" capability "Health Check" + capability "Light" attribute "colorName", "string" command "setGenericName" @@ -139,7 +141,7 @@ def ping() { } def refresh() { - zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_COLOR_TEMPERATURE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION) + zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, 0x20, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, 0x20, 1, 3600, 0x01) + zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_COLOR_TEMPERATURE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION) + zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, DataType.UINT8, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, DataType.UINT8, 1, 3600, 0x01) } def configure() { @@ -192,3 +194,11 @@ def setSaturation(value) { def scaledSatValue = zigbee.convertToHexString(Math.round(value * 0xfe / 100.0), 2) zigbee.command(COLOR_CONTROL_CLUSTER, SATURATION_COMMAND, scaledSatValue, "0500") + "delay 1000" + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION) } + +def installed() { + if (((device.getDataValue("manufacturer") == "MRVL") && (device.getDataValue("model") == "MZ100")) || (device.getDataValue("manufacturer") == "OSRAM SYLVANIA") || (device.getDataValue("manufacturer") == "OSRAM")) { + if ((device.currentState("level")?.value == null) || (device.currentState("level")?.value == 0)) { + sendEvent(name: "level", value: 100) + } + } +} \ No newline at end of file diff --git a/devicetypes/smartthings/zigbee-switch-power.src/zigbee-switch-power.groovy b/devicetypes/smartthings/zigbee-switch-power.src/zigbee-switch-power.groovy index c118fe6..9253465 100644 --- a/devicetypes/smartthings/zigbee-switch-power.src/zigbee-switch-power.groovy +++ b/devicetypes/smartthings/zigbee-switch-power.src/zigbee-switch-power.groovy @@ -21,6 +21,7 @@ metadata { capability "Sensor" capability "Switch" capability "Health Check" + capability "Light" fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0B04" fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0702" @@ -32,9 +33,9 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" } tileAttribute ("power", key: "SECONDARY_CONTROL") { diff --git a/devicetypes/smartthings/zigbee-switch.src/zigbee-switch.groovy b/devicetypes/smartthings/zigbee-switch.src/zigbee-switch.groovy index fc4debb..34192de 100644 --- a/devicetypes/smartthings/zigbee-switch.src/zigbee-switch.groovy +++ b/devicetypes/smartthings/zigbee-switch.src/zigbee-switch.groovy @@ -22,6 +22,8 @@ metadata { fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006" fingerprint profileId: "0104", inClusters: "0000, 0003, 0006", outClusters: "0003, 0006, 0019, 0406", manufacturer: "Leviton", model: "ZSS-10", deviceJoinName: "Leviton Switch" fingerprint profileId: "0104", inClusters: "0000, 0003, 0006", outClusters: "000A", manufacturer: "HAI", model: "65A21-1", deviceJoinName: "Leviton Wireless Load Control Module-30amp" + fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006", outClusters: "0003, 0006, 0008, 0019, 0406", manufacturer: "Leviton", model: "DL15A", deviceJoinName: "Leviton Lumina RF Plug-In Appliance Module" + fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006", outClusters: "0003, 0006, 0008, 0019, 0406", manufacturer: "Leviton", model: "DL15S", deviceJoinName: "Leviton Lumina RF Switch" } // simulator metadata diff --git a/devicetypes/smartthings/zigbee-valve.src/zigbee-valve.groovy b/devicetypes/smartthings/zigbee-valve.src/zigbee-valve.groovy index 4b66fc6..657da69 100644 --- a/devicetypes/smartthings/zigbee-valve.src/zigbee-valve.groovy +++ b/devicetypes/smartthings/zigbee-valve.src/zigbee-valve.groovy @@ -11,6 +11,7 @@ * for the specific language governing permissions and limitations under the License. * */ +import physicalgraph.zigbee.zcl.DataType metadata { definition (name: "ZigBee Valve", namespace: "smartthings", author: "SmartThings") { @@ -39,10 +40,10 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"valve", type: "generic", width: 6, height: 4, canChangeIcon: true){ tileAttribute ("device.contact", key: "PRIMARY_CONTROL") { - attributeState "open", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#53a7c0", nextState:"closing" - attributeState "closed", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#e86d13", nextState:"opening" - attributeState "opening", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#53a7c0", nextState:"closing" - attributeState "closing", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#e86d13", nextState:"opening" + attributeState "open", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#00A0DC", nextState:"closing" + attributeState "closed", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#ffffff", nextState:"opening" + attributeState "opening", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#00A0DC", nextState:"closing" + attributeState "closing", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#ffffff", nextState:"opening" } tileAttribute ("powerSource", key: "SECONDARY_CONTROL") { attributeState "powerSource", label:'Power Source: ${currentValue}' @@ -66,8 +67,6 @@ private getCLUSTER_BASIC() { 0x0000 } private getBASIC_ATTR_POWER_SOURCE() { 0x0007 } private getCLUSTER_POWER() { 0x0001 } private getPOWER_ATTR_BATTERY_PERCENTAGE_REMAINING() { 0x0021 } -private getTYPE_U8() { 0x20 } -private getTYPE_ENUM8() { 0x30 } // Parse incoming device messages to generate events def parse(String description) { @@ -128,8 +127,8 @@ def refresh() { zigbee.readAttribute(CLUSTER_BASIC, BASIC_ATTR_POWER_SOURCE) + zigbee.readAttribute(CLUSTER_POWER, POWER_ATTR_BATTERY_PERCENTAGE_REMAINING) + zigbee.onOffConfig() + - zigbee.configureReporting(CLUSTER_POWER, POWER_ATTR_BATTERY_PERCENTAGE_REMAINING, TYPE_U8, 600, 21600, 1) + - zigbee.configureReporting(CLUSTER_BASIC, BASIC_ATTR_POWER_SOURCE, TYPE_ENUM8, 5, 21600, 1) + zigbee.configureReporting(CLUSTER_POWER, POWER_ATTR_BATTERY_PERCENTAGE_REMAINING, DataType.UINT8, 600, 21600, 1) + + zigbee.configureReporting(CLUSTER_BASIC, BASIC_ATTR_POWER_SOURCE, DataType.ENUM8, 5, 21600, 1) } def configure() { diff --git a/devicetypes/smartthings/zigbee-white-color-temperature-bulb.src/zigbee-white-color-temperature-bulb.groovy b/devicetypes/smartthings/zigbee-white-color-temperature-bulb.src/zigbee-white-color-temperature-bulb.groovy index d6e69e1..5e7a2bc 100644 --- a/devicetypes/smartthings/zigbee-white-color-temperature-bulb.src/zigbee-white-color-temperature-bulb.groovy +++ b/devicetypes/smartthings/zigbee-white-color-temperature-bulb.src/zigbee-white-color-temperature-bulb.groovy @@ -26,6 +26,7 @@ metadata { capability "Refresh" capability "Switch" capability "Switch Level" + capability "Light" attribute "colorName", "string" command "setGenericName" @@ -156,3 +157,11 @@ def setGenericName(value){ sendEvent(name: "colorName", value: genericName) } } + +def installed() { + if (((device.getDataValue("manufacturer") == "MRVL") && (device.getDataValue("model") == "MZ100")) || (device.getDataValue("manufacturer") == "OSRAM SYLVANIA") || (device.getDataValue("manufacturer") == "OSRAM")) { + if ((device.currentState("level")?.value == null) || (device.currentState("level")?.value == 0)) { + sendEvent(name: "level", value: 100) + } + } +} diff --git a/devicetypes/smartthings/zll-dimmer-bulb.src/zll-dimmer-bulb.groovy b/devicetypes/smartthings/zll-dimmer-bulb.src/zll-dimmer-bulb.groovy index cce0862..a0568e7 100644 --- a/devicetypes/smartthings/zll-dimmer-bulb.src/zll-dimmer-bulb.groovy +++ b/devicetypes/smartthings/zll-dimmer-bulb.src/zll-dimmer-bulb.groovy @@ -89,7 +89,7 @@ def on() { } def setLevel(value) { - zigbee.setLevel(value) + ["delay 1500"] + zigbee.levelRefresh() //adding refresh because of ZLL bulb not conforming to send-me-a-report + zigbee.setLevel(value) + zigbee.onOffRefresh() + zigbee.levelRefresh() //adding refresh because of ZLL bulb not conforming to send-me-a-report } def refresh() { diff --git a/devicetypes/smartthings/zll-rgb-bulb.src/zll-rgb-bulb.groovy b/devicetypes/smartthings/zll-rgb-bulb.src/zll-rgb-bulb.groovy index 5988334..1e5345f 100644 --- a/devicetypes/smartthings/zll-rgb-bulb.src/zll-rgb-bulb.groovy +++ b/devicetypes/smartthings/zll-rgb-bulb.src/zll-rgb-bulb.groovy @@ -11,6 +11,7 @@ * for the specific language governing permissions and limitations under the License. * */ +import physicalgraph.zigbee.zcl.DataType metadata { definition (name: "ZLL RGB Bulb", namespace: "smartthings", author: "SmartThings") { @@ -28,9 +29,9 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" } tileAttribute ("device.level", key: "SLIDER_CONTROL") { @@ -107,7 +108,7 @@ def configure() { } def configureAttributes() { - zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, 0x20, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, 0x20, 1, 3600, 0x01) + zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, DataType.UINT8, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, DataType.UINT8, 1, 3600, 0x01) } def refreshAttributes() { @@ -115,7 +116,7 @@ def refreshAttributes() { } def setLevel(value) { - zigbee.setLevel(value) + ["delay 1500"] + zigbee.levelRefresh() //adding refresh because of ZLL bulb not conforming to send-me-a-report + zigbee.setLevel(value) + zigbee.onOffRefresh() + zigbee.levelRefresh() //adding refresh because of ZLL bulb not conforming to send-me-a-report } def setColor(value){ diff --git a/devicetypes/smartthings/zll-rgbw-bulb.src/zll-rgbw-bulb.groovy b/devicetypes/smartthings/zll-rgbw-bulb.src/zll-rgbw-bulb.groovy index 5d9e700..74cb921 100644 --- a/devicetypes/smartthings/zll-rgbw-bulb.src/zll-rgbw-bulb.groovy +++ b/devicetypes/smartthings/zll-rgbw-bulb.src/zll-rgbw-bulb.groovy @@ -11,6 +11,7 @@ * for the specific language governing permissions and limitations under the License. * */ +import physicalgraph.zigbee.zcl.DataType metadata { definition (name: "ZLL RGBW Bulb", namespace: "smartthings", author: "SmartThings") { @@ -37,9 +38,9 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" } tileAttribute ("device.level", key: "SLIDER_CONTROL") { @@ -123,7 +124,7 @@ def configure() { } def configureAttributes() { - zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, 0x20, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, 0x20, 1, 3600, 0x01) + zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, DataType.UINT8, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, DataType.UINT8, 1, 3600, 0x01) } def refreshAttributes() { @@ -135,7 +136,7 @@ def setColorTemperature(value) { } def setLevel(value) { - zigbee.setLevel(value) + ["delay 1500"] + zigbee.levelRefresh() //adding refresh because of ZLL bulb not conforming to send-me-a-report + zigbee.setLevel(value) + zigbee.onOffRefresh() + zigbee.levelRefresh() //adding refresh because of ZLL bulb not conforming to send-me-a-report } def setColor(value){ diff --git a/devicetypes/smartthings/zll-white-color-temperature-bulb-5000k.src/zll-white-color-temperature-bulb-5000k.groovy b/devicetypes/smartthings/zll-white-color-temperature-bulb-5000k.src/zll-white-color-temperature-bulb-5000k.groovy new file mode 100644 index 0000000..3c88380 --- /dev/null +++ b/devicetypes/smartthings/zll-white-color-temperature-bulb-5000k.src/zll-white-color-temperature-bulb-5000k.groovy @@ -0,0 +1,169 @@ +/** + * Copyright 2016 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. + * + */ +import groovy.transform.Field + +@Field Boolean hasConfiguredHealthCheck = false + +metadata { + definition (name: "ZLL White Color Temperature Bulb 5000K", namespace: "smartthings", author: "SmartThings") { + + capability "Actuator" + capability "Color Temperature" + capability "Configuration" + capability "Polling" + capability "Refresh" + capability "Switch" + capability "Switch Level" + capability "Health Check" + + attribute "colorName", "string" + command "setGenericName" + + fingerprint profileId: "C05E", deviceId: "0220", inClusters: "0000, 0004, 0003, 0006, 0008, 0005, 0300", outClusters: "0019", manufacturer: "Eaton", model: "Halo_LT01", deviceJoinName: "Halo RL56 Wireless" + } + + // UI tile definitions + tiles(scale: 2) { + multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ + tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { + attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#00A0DC", nextState:"turningOff" + attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn" + attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#00A0DC", nextState:"turningOff" + attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn" + } + tileAttribute ("device.level", key: "SLIDER_CONTROL") { + attributeState "level", action:"switch level.setLevel" + } + tileAttribute ("colorName", key: "SECONDARY_CONTROL") { + attributeState "colorName", label:'${currentValue}' + } + } + + standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { + state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh" + } + + controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2700..5000)") { + state "colorTemperature", action:"color temperature.setColorTemperature" + } + valueTile("colorTemp", "device.colorTemperature", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { + state "colorTemperature", label: '${currentValue} K' + } + + main(["switch"]) + details(["switch", "colorTempSliderControl", "colorTemp", "refresh"]) + } +} + +// Parse incoming device messages to generate events +def parse(String description) { + log.debug "description is $description" + def event = zigbee.getEvent(description) + if (event) { + if (event.name == "colorTemperature") { + event.unit = "K" + } + sendEvent(event) + } + else { + log.warn "DID NOT PARSE MESSAGE for description : $description" + log.debug zigbee.parseDescriptionAsMap(description) + } +} + +def off() { + zigbee.off() + ["delay 1500"] + zigbee.onOffRefresh() +} + +def on() { + zigbee.on() + ["delay 1500"] + zigbee.onOffRefresh() +} + +def setLevel(value) { + zigbee.setLevel(value) + zigbee.onOffRefresh() + zigbee.levelRefresh() +} + +def refresh() { + def cmds = zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh() + + // Do NOT config if the device is the Eaton Halo_LT01, it responds with "switch:off" to onOffConfig, and maybe other weird things with the others + if (!((device.getDataValue("manufacturer") == "Eaton") && (device.getDataValue("model") == "Halo_LT01"))) { + cmds = cmds + zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + } + + cmds +} + +def poll() { + zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh() +} + +/** + * PING is used by Device-Watch in attempt to reach the Device + * */ +def ping() { + return zigbee.levelRefresh() +} + +def healthPoll() { + log.debug "healthPoll()" + def cmds = zigbee.onOffRefresh() + zigbee.levelRefresh() + cmds.each{ sendHubCommand(new physicalgraph.device.HubAction(it))} +} + +def configureHealthCheck() { + Integer hcIntervalMinutes = 12 + if (!hasConfiguredHealthCheck) { + log.debug "Configuring Health Check, Reporting" + unschedule("healthPoll") + runEvery5Minutes("healthPoll") + // Device-Watch allows 2 check-in misses from device + sendEvent(name: "checkInterval", value: hcIntervalMinutes * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) + hasConfiguredHealthCheck = true + } +} + +def configure() { + log.debug "configure()" + configureHealthCheck() + // Implementation note: for the Eaton Halo_LT01, it responds with "switch:off" to onOffConfig, so be sure this is before the call to onOffRefresh + zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh() +} + +def updated() { + log.debug "updated()" + configureHealthCheck() +} + +def setColorTemperature(value) { + setGenericName(value) + zigbee.setColorTemperature(value) + ["delay 1500"] + zigbee.colorTemperatureRefresh() +} + +//Naming based on the wiki article here: http://en.wikipedia.org/wiki/Color_temperature +def setGenericName(value){ + if (value != null) { + def genericName = "" + if (value < 3300) { + genericName = "Soft White" + } else if (value < 4150) { + genericName = "Moonlight" + } else if (value <= 5000) { + genericName = "Cool White" + } else { + genericName = "Daylight" + } + sendEvent(name: "colorName", value: genericName, displayed: false) + } +} diff --git a/devicetypes/smartthings/zll-white-color-temperature-bulb.src/zll-white-color-temperature-bulb.groovy b/devicetypes/smartthings/zll-white-color-temperature-bulb.src/zll-white-color-temperature-bulb.groovy index 98ddddd..ee3130d 100644 --- a/devicetypes/smartthings/zll-white-color-temperature-bulb.src/zll-white-color-temperature-bulb.groovy +++ b/devicetypes/smartthings/zll-white-color-temperature-bulb.src/zll-white-color-temperature-bulb.groovy @@ -39,9 +39,9 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#00A0DC", nextState:"turningOff" attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn" } tileAttribute ("device.level", key: "SLIDER_CONTROL") { @@ -90,7 +90,7 @@ def on() { } def setLevel(value) { - zigbee.setLevel(value) + ["delay 1500"] + zigbee.levelRefresh() + zigbee.setLevel(value) + zigbee.onOffRefresh() + zigbee.levelRefresh() } def refresh() { diff --git a/devicetypes/smartthings/zwave-device-multichannel.src/zwave-device-multichannel.groovy b/devicetypes/smartthings/zwave-device-multichannel.src/zwave-device-multichannel.groovy index 14b05d0..89b972b 100644 --- a/devicetypes/smartthings/zwave-device-multichannel.src/zwave-device-multichannel.groovy +++ b/devicetypes/smartthings/zwave-device-multichannel.src/zwave-device-multichannel.groovy @@ -40,7 +40,7 @@ metadata { tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { - state "on", label: '${name}', action: "switch.off", icon: "st.unknown.zwave.device", backgroundColor: "#79b821" + state "on", label: '${name}', action: "switch.off", icon: "st.unknown.zwave.device", backgroundColor: "#00A0DC" state "off", label: '${name}', action: "switch.on", icon: "st.unknown.zwave.device", backgroundColor: "#ffffff" } standardTile("switchOn", "device.switch", inactiveLabel: false, decoration: "flat") { diff --git a/devicetypes/smartthings/zwave-device.src/zwave-device.groovy b/devicetypes/smartthings/zwave-device.src/zwave-device.groovy index 2c4958f..932f4bf 100644 --- a/devicetypes/smartthings/zwave-device.src/zwave-device.groovy +++ b/devicetypes/smartthings/zwave-device.src/zwave-device.groovy @@ -33,7 +33,7 @@ metadata { tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { - state "on", label: '${name}', action: "switch.off", icon: "st.unknown.zwave.device", backgroundColor: "#79b821" + state "on", label: '${name}', action: "switch.off", icon: "st.unknown.zwave.device", backgroundColor: "#00A0DC" state "off", label: '${name}', action: "switch.on", icon: "st.unknown.zwave.device", backgroundColor: "#ffffff" } standardTile("switchOn", "device.switch", inactiveLabel: false, decoration: "flat") { diff --git a/devicetypes/smartthings/zwave-dimmer-switch-generic.src/README.md b/devicetypes/smartthings/zwave-dimmer-switch-generic.src/README.md index d959894..a76bbd7 100644 --- a/devicetypes/smartthings/zwave-dimmer-switch-generic.src/README.md +++ b/devicetypes/smartthings/zwave-dimmer-switch-generic.src/README.md @@ -6,6 +6,12 @@ Works with: * [Leviton Plug-in Lamp Dimmer Module (DZPD3-1LW)](https://www.smartthings.com/works-with-smartthings/outlets/leviton-plug-in-lamp-dimmer-module) * [Leviton Universal Dimmer (DZMX1-LZ)](https://www.smartthings.com/works-with-smartthings/switches-and-dimmers/leviton-universal-dimmer) +* [Leviton 1000W Incandescent Dimmer](https://www.smartthings.com/works-with-smartthings/leviton/leviton-1000w-incandescent-dimmer) +* [Leviton 600W Incandescent Dimmer](https://www.smartthings.com/works-with-smartthings/leviton/leviton-600w-incandescent-dimmer) +* [Enerwave In-Wall Dimmer](https://www.smartthings.com/works-with-smartthings/enerwave/enerwave-in-wall-dimmer-zw500d) +* [Leviton 3-Speed Fan Controller](https://www.smartthings.com/works-with-smartthings/leviton/leviton-3-speed-fan-controller) +* [Leviton Magnetic Low Voltage Dimmer](https://www.smartthings.com/works-with-smartthings/leviton/leviton-magnetic-low-voltage-dimmer) +* [Remotec Technology Plug-In Dimmer](https://www.smartthings.com/works-with-smartthings/remotec-technology/remotec-technology-plug-in-dimmer) ## Table of contents @@ -40,4 +46,9 @@ If the device doesn't pair when trying from the SmartThings mobile app, it is po Pairing needs to be tried again by placing the device closer to the hub. Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link: * [Leviton Plug-in Lamp Dimmer Module (DZPD3-1LW) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206171053-How-to-connect-Leviton-Z-Wave-devices) -* [Leviton Universal Dimmer (DZMX1-LZ) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206171053-How-to-connect-Leviton-Z-Wave-devices) \ No newline at end of file +* [Leviton Universal Dimmer (DZMX1-LZ) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206171053-How-to-connect-Leviton-Z-Wave-devices) +* [Leviton 1000W Incandescent Dimmer Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206171053-How-to-connect-Leviton-Z-Wave-devices) +* [Leviton 600W Incandescent Dimmer Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206171053-How-to-connect-Leviton-Z-Wave-devices) +* [Leviton 3-Speed Fan Controller Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206171053-How-to-connect-Leviton-Z-Wave-devices) +* [Enerwave In-Wall Dimmer Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/204854176-How-to-connect-Enerwave-switches-and-dimmers) +* [Remotec Technology Plug-In Dimmer Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/202295150-Remotec-Technology-Plug-In-Dimmer-ZDS-100-) \ No newline at end of file diff --git a/devicetypes/smartthings/zwave-dimmer-switch-generic.src/zwave-dimmer-switch-generic.groovy b/devicetypes/smartthings/zwave-dimmer-switch-generic.src/zwave-dimmer-switch-generic.groovy index 43a65b8..7c9c575 100644 --- a/devicetypes/smartthings/zwave-dimmer-switch-generic.src/zwave-dimmer-switch-generic.groovy +++ b/devicetypes/smartthings/zwave-dimmer-switch-generic.src/zwave-dimmer-switch-generic.groovy @@ -20,10 +20,17 @@ metadata { capability "Polling" capability "Refresh" capability "Sensor" + capability "Light" fingerprint inClusters: "0x26", deviceJoinName: "Z-Wave Dimmer" fingerprint mfr:"001D", prod:"1902", deviceJoinName: "Z-Wave Dimmer" fingerprint mfr:"001D", prod:"1B03", model:"0334", deviceJoinName: "Leviton Universal Dimmer" + fingerprint mfr:"011A", prod:"0102", model:"0201", deviceJoinName: "Enerwave In-Wall Dimmer" + fingerprint mfr:"001D", prod:"1001", model:"0334", deviceJoinName: "Leviton 3-Speed Fan Controller" + fingerprint mfr:"001D", prod:"0602", model:"0334", deviceJoinName: "Leviton Magnetic Low Voltage Dimmer" + fingerprint mfr:"001D", prod:"0401", model:"0334", deviceJoinName: "Leviton 600W Incandescent Dimmer" + fingerprint mfr:"0111", prod:"8200", model:"0200", deviceJoinName: "Remotec Technology Plug-In Dimmer" + fingerprint mfr:"1104", prod:"001D", model:"0501", deviceJoinName: "Leviton 1000W Incandescant Dimmer" } simulator { @@ -47,9 +54,9 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00a0dc", nextState:"turningOff" attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" + attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00a0dc", nextState:"turningOff" attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" } tileAttribute ("device.level", key: "SLIDER_CONTROL") { diff --git a/devicetypes/smartthings/zwave-door-window-sensor.src/zwave-door-window-sensor.groovy b/devicetypes/smartthings/zwave-door-window-sensor.src/zwave-door-window-sensor.groovy index fb46c0e..ff8491d 100644 --- a/devicetypes/smartthings/zwave-door-window-sensor.src/zwave-door-window-sensor.groovy +++ b/devicetypes/smartthings/zwave-door-window-sensor.src/zwave-door-window-sensor.groovy @@ -41,8 +41,8 @@ metadata { // UI tile definitions 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" + state "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#e86d13" + state "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#00A0DC" } valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") { state "battery", label:'${currentValue}% battery', unit:"" diff --git a/devicetypes/smartthings/zwave-garage-door-opener.src/.st-ignore b/devicetypes/smartthings/zwave-garage-door-opener.src/.st-ignore new file mode 100644 index 0000000..f78b46e --- /dev/null +++ b/devicetypes/smartthings/zwave-garage-door-opener.src/.st-ignore @@ -0,0 +1,2 @@ +.st-ignore +README.md diff --git a/devicetypes/smartthings/zwave-garage-door-opener.src/README.md b/devicetypes/smartthings/zwave-garage-door-opener.src/README.md new file mode 100644 index 0000000..188521d --- /dev/null +++ b/devicetypes/smartthings/zwave-garage-door-opener.src/README.md @@ -0,0 +1,41 @@ +# Z-wave Garage Door Opener + +Cloud Execution + +Works with: + +* [Linear GoControl Garage Door Opener](https://www.smartthings.com/works-with-smartthings/other/linear-gocontrol-garage-door-opener) + +## Table of contents + +* [Capabilities](#capabilities) +* [Health](#device-health) +* [Troubleshooting](#troubleshooting) + +## Capabilities + +* **Actuator** - represents that a Device has commands +* **Door Control** - allow for the control of a door +* **Garage Door Control** - allow for the control of a garage door +* **Health Check** - indicates ability to get device health notifications +* **Contact Sensor** - can detect contact (with possible values - open/closed) +* **Refresh** - _refresh()_ command for status updates +* **Sensor** - detects sensor events + +## Device Health + +Linear GoControl Garage Door Opener is polled by the hub. +As of hubCore version 0.14.38 the hub sends up reports every 15 minutes regardless of whether the state changed. +Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*15 + 2)mins = 32 mins. +Not to mention after going OFFLINE when the device is plugged back in, it might take a considerable amount of time for +the device to appear as ONLINE again. This is because if this listening device does not respond to two poll requests in a row, +it is not polled for 5 minutes by the hub. This can delay up the process of being marked ONLINE by quite some time. + +* __32min__ checkInterval + +## Troubleshooting + +If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range. +Pairing needs to be tried again by placing the device closer to the hub. +Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link: +* [Linear GoControl Garage Door Opener Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/204831116-GoControl-Linear-Garage-Door-Opener-GD00Z-4-) \ No newline at end of file diff --git a/devicetypes/smartthings/zwave-garage-door-opener.src/zwave-garage-door-opener.groovy b/devicetypes/smartthings/zwave-garage-door-opener.src/zwave-garage-door-opener.groovy index f22faf8..65357e4 100644 --- a/devicetypes/smartthings/zwave-garage-door-opener.src/zwave-garage-door-opener.groovy +++ b/devicetypes/smartthings/zwave-garage-door-opener.src/zwave-garage-door-opener.groovy @@ -18,12 +18,14 @@ metadata { capability "Actuator" capability "Door Control" capability "Garage Door Control" + capability "Health Check" capability "Contact Sensor" capability "Refresh" capability "Sensor" fingerprint deviceId: "0x4007", inClusters: "0x98" fingerprint deviceId: "0x4006", inClusters: "0x98" + fingerprint mfr:"014F", prod:"4744", model:"3030", deviceJoinName: "Linear GoControl Garage Door Opener" } simulator { @@ -39,11 +41,11 @@ metadata { tiles { standardTile("toggle", "device.door", width: 2, height: 2) { - state("unknown", label:'${name}', action:"refresh.refresh", icon:"st.doors.garage.garage-open", backgroundColor:"#ffa81e") - state("closed", label:'${name}', action:"door control.open", icon:"st.doors.garage.garage-closed", backgroundColor:"#79b821", nextState:"opening") - state("open", label:'${name}', action:"door control.close", icon:"st.doors.garage.garage-open", backgroundColor:"#ffa81e", nextState:"closing") - state("opening", label:'${name}', icon:"st.doors.garage.garage-opening", backgroundColor:"#ffe71e") - state("closing", label:'${name}', icon:"st.doors.garage.garage-closing", backgroundColor:"#ffe71e") + state("unknown", label:'${name}', action:"refresh.refresh", icon:"st.doors.garage.garage-open", backgroundColor:"#ffffff") + state("closed", label:'${name}', action:"door control.open", icon:"st.doors.garage.garage-closed", backgroundColor:"#00a0dc", nextState:"opening") + state("open", label:'${name}', action:"door control.close", icon:"st.doors.garage.garage-open", backgroundColor:"#e86d13", nextState:"closing") + state("opening", label:'${name}', icon:"st.doors.garage.garage-opening", backgroundColor:"#e86d13") + state("closing", label:'${name}', icon:"st.doors.garage.garage-closing", backgroundColor:"#00a0dc") } standardTile("open", "device.door", inactiveLabel: false, decoration: "flat") { @@ -63,6 +65,11 @@ metadata { import physicalgraph.zwave.commands.barrieroperatorv1.* +def updated(){ +// Device-Watch simply pings if no device events received for 32min(checkInterval) + sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) +} + def parse(String description) { def result = null if (description.startsWith("Err")) { @@ -287,6 +294,13 @@ def close() { secure(zwave.barrierOperatorV1.barrierOperatorSet(requestedBarrierState: BarrierOperatorSet.REQUESTED_BARRIER_STATE_CLOSE)) } +/** + * PING is used by Device-Watch in attempt to reach the Device + * */ +def ping() { + refresh() +} + def refresh() { secure(zwave.barrierOperatorV1.barrierOperatorGet()) } diff --git a/devicetypes/smartthings/zwave-lock.src/.st-ignore b/devicetypes/smartthings/zwave-lock.src/.st-ignore new file mode 100644 index 0000000..f78b46e --- /dev/null +++ b/devicetypes/smartthings/zwave-lock.src/.st-ignore @@ -0,0 +1,2 @@ +.st-ignore +README.md diff --git a/devicetypes/smartthings/zwave-lock.src/README.md b/devicetypes/smartthings/zwave-lock.src/README.md new file mode 100644 index 0000000..ae64536 --- /dev/null +++ b/devicetypes/smartthings/zwave-lock.src/README.md @@ -0,0 +1,45 @@ +# Z-Wave Switch + +Cloud Execution + +Works with: + +* [Yale Key Free Touchscreen Deadbolt (YRD240)](https://www.smartthings.com/works-with-smartthings/yale/yale-key-free-touchscreen-deadbolt-yrd240) + + +## Table of contents + +* [Capabilities](#capabilities) +* [Health](#device-health) +* [Troubleshooting](#Troubleshooting) + +## Capabilities + +* **Actuator** - represents that a Device has commands +* **Battery** - defines device uses a battery +* **Lock** - allows for the control of a lock device +* **Lock Codes** - allows for the lock code control of a lock device +* **Polling** - represents that poll() can be implemented for the device +* **Refresh** - _refresh()_ command for status updates +* **Sensor** - detects sensor events +* **Health Check** - indicates ability to get device health notifications + +## Device Health + +Z-Wave Locks are polled by the hub. +As of hubCore version 0.14.38 the hub sends up reports every 15 minutes regardless of whether the state changed. +Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*15 + 2)mins = 32 mins. +Not to mention after going OFFLINE when the device is plugged back in, it might take a considerable amount of time for +the device to appear as ONLINE again. This is because if this listening device does not respond to two poll requests in a row, +it is not polled for 5 minutes by the hub. This can delay up the process of being marked ONLINE by quite some time. + +* __32min__ checkInterval + +## Troubleshooting + +If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range. +Pairing needs to be tried again by placing the device closer to the hub. +Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link: +* [General Z-Wave/ZigBee Yale Lock Troubleshooting](https://support.smartthings.com/hc/en-us/articles/205138400-How-to-connect-Yale-locks) + + diff --git a/devicetypes/smartthings/zwave-lock.src/zwave-lock.groovy b/devicetypes/smartthings/zwave-lock.src/zwave-lock.groovy index 0535ffa..697fe3d 100644 --- a/devicetypes/smartthings/zwave-lock.src/zwave-lock.groovy +++ b/devicetypes/smartthings/zwave-lock.src/zwave-lock.groovy @@ -20,11 +20,13 @@ metadata { capability "Sensor" capability "Lock Codes" capability "Battery" + capability "Health Check" command "unlockwtimeout" fingerprint deviceId: "0x4003", inClusters: "0x98" fingerprint deviceId: "0x4004", inClusters: "0x98" + fingerprint mfr:"0129", prod:"0002", model:"0000", deviceJoinName: "Yale Key Free Touchscreen Deadbolt" } simulator { @@ -38,10 +40,10 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"toggle", type: "generic", width: 6, height: 4){ tileAttribute ("device.lock", key: "PRIMARY_CONTROL") { - attributeState "locked", label:'locked', action:"lock.unlock", icon:"st.locks.lock.locked", backgroundColor:"#79b821", nextState:"unlocking" + attributeState "locked", label:'locked', action:"lock.unlock", icon:"st.locks.lock.locked", backgroundColor:"#00A0DC", nextState:"unlocking" attributeState "unlocked", label:'unlocked', action:"lock.lock", icon:"st.locks.lock.unlocked", backgroundColor:"#ffffff", nextState:"locking" attributeState "unknown", label:"unknown", action:"lock.lock", icon:"st.locks.lock.unknown", backgroundColor:"#ffffff", nextState:"locking" - attributeState "locking", label:'locking', icon:"st.locks.lock.locked", backgroundColor:"#79b821" + attributeState "locking", label:'locking', icon:"st.locks.lock.locked", backgroundColor:"#00A0DC" attributeState "unlocking", label:'unlocking', icon:"st.locks.lock.unlocked", backgroundColor:"#ffffff" } } @@ -67,6 +69,8 @@ import physicalgraph.zwave.commands.doorlockv1.* import physicalgraph.zwave.commands.usercodev1.* def updated() { + // Device-Watch simply pings if no device events received for 32min(checkInterval) + sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) try { if (!state.init) { state.init = true @@ -504,6 +508,13 @@ def unlockwtimeout() { lockAndCheck(DoorLockOperationSet.DOOR_LOCK_MODE_DOOR_UNSECURED_WITH_TIMEOUT) } +/** + * PING is used by Device-Watch in attempt to reach the Device + * */ +def ping() { + refresh() +} + def refresh() { def cmds = [secure(zwave.doorLockV1.doorLockOperationGet())] if (state.assoc == zwaveHubNodeId) { diff --git a/devicetypes/smartthings/zwave-metering-dimmer.src/zwave-metering-dimmer.groovy b/devicetypes/smartthings/zwave-metering-dimmer.src/zwave-metering-dimmer.groovy index 4631203..4b2fba2 100644 --- a/devicetypes/smartthings/zwave-metering-dimmer.src/zwave-metering-dimmer.groovy +++ b/devicetypes/smartthings/zwave-metering-dimmer.src/zwave-metering-dimmer.groovy @@ -25,6 +25,7 @@ metadata { capability "Switch Level" capability "Sensor" capability "Actuator" + capability "Light" command "reset" @@ -56,9 +57,9 @@ metadata { tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { - state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" + state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff" state "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" - state "turningOn", label:'${name}', icon:"st.switches.switch.on", backgroundColor:"#79b821" + state "turningOn", label:'${name}', icon:"st.switches.switch.on", backgroundColor:"#00A0DC" state "turningOff", label:'${name}', icon:"st.switches.switch.off", backgroundColor:"#ffffff" } valueTile("power", "device.power") { diff --git a/devicetypes/smartthings/zwave-metering-switch.src/zwave-metering-switch.groovy b/devicetypes/smartthings/zwave-metering-switch.src/zwave-metering-switch.groovy index 5f3db81..3655220 100644 --- a/devicetypes/smartthings/zwave-metering-switch.src/zwave-metering-switch.groovy +++ b/devicetypes/smartthings/zwave-metering-switch.src/zwave-metering-switch.groovy @@ -53,7 +53,7 @@ metadata { // tile definitions tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { - state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" + state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC" state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" } valueTile("power", "device.power") { diff --git a/devicetypes/smartthings/zwave-motion-sensor.src/zwave-motion-sensor.groovy b/devicetypes/smartthings/zwave-motion-sensor.src/zwave-motion-sensor.groovy index 014900b..a5003c3 100644 --- a/devicetypes/smartthings/zwave-motion-sensor.src/zwave-motion-sensor.groovy +++ b/devicetypes/smartthings/zwave-motion-sensor.src/zwave-motion-sensor.groovy @@ -28,6 +28,7 @@ metadata { fingerprint mfr: "0060", prod: "0001", model: "0002", deviceJoinName: "Everspring Motion Sensor" // Everspring SP814 fingerprint mfr: "0060", prod: "0001", model: "0003", deviceJoinName: "Everspring Motion Sensor" // Everspring HSP02 fingerprint mfr: "011A", prod: "0601", model: "0901", deviceJoinName: "Enerwave Motion Sensor" // Enerwave ZWN-BPC + fingerprint mfr: "0063", prod: "4953", model: "3133", deviceJoinName: "GE Smart Motion Sensor" } simulator { @@ -37,8 +38,8 @@ metadata { tiles { standardTile("motion", "device.motion", width: 2, height: 2) { - state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0") - state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff") + state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC") + state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc") } valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") { state("battery", label:'${currentValue}% battery', unit:"") diff --git a/devicetypes/smartthings/zwave-plus-door-window-sensor.src/zwave-plus-door-window-sensor.groovy b/devicetypes/smartthings/zwave-plus-door-window-sensor.src/zwave-plus-door-window-sensor.groovy index 93df68a..403e5d9 100644 --- a/devicetypes/smartthings/zwave-plus-door-window-sensor.src/zwave-plus-door-window-sensor.groovy +++ b/devicetypes/smartthings/zwave-plus-door-window-sensor.src/zwave-plus-door-window-sensor.groovy @@ -37,8 +37,8 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"contact", type: "generic", width: 6, height: 4){ tileAttribute ("device.contact", key: "PRIMARY_CONTROL") { - attributeState "open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e" - attributeState "closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821" + attributeState "open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#e86d13" + attributeState "closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#00a0dc" } } valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) { diff --git a/devicetypes/smartthings/zwave-relay.src/zwave-relay.groovy b/devicetypes/smartthings/zwave-relay.src/zwave-relay.groovy index 7088340..ca6365e 100644 --- a/devicetypes/smartthings/zwave-relay.src/zwave-relay.groovy +++ b/devicetypes/smartthings/zwave-relay.src/zwave-relay.groovy @@ -38,7 +38,7 @@ metadata { // tile definitions tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { - state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" + state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00a0dc" state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" } standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") { diff --git a/devicetypes/smartthings/zwave-sensor.src/zwave-sensor.groovy b/devicetypes/smartthings/zwave-sensor.src/zwave-sensor.groovy index 16f991c..3d5746c 100644 --- a/devicetypes/smartthings/zwave-sensor.src/zwave-sensor.groovy +++ b/devicetypes/smartthings/zwave-sensor.src/zwave-sensor.groovy @@ -32,8 +32,8 @@ metadata { tiles { standardTile("sensor", "device.sensor", width: 2, height: 2) { - state("inactive", label:'inactive', icon:"st.unknown.zwave.sensor", backgroundColor:"#ffffff") - state("active", label:'active', icon:"st.unknown.zwave.sensor", backgroundColor:"#53a7c0") + state("inactive", label:'inactive', icon:"st.unknown.zwave.sensor", backgroundColor:"#cccccc") + state("active", label:'active', icon:"st.unknown.zwave.sensor", backgroundColor:"#00A0DC") } valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") { state "battery", label:'${currentValue}% battery', unit:"" diff --git a/devicetypes/smartthings/zwave-siren.src/.st-ignore b/devicetypes/smartthings/zwave-siren.src/.st-ignore new file mode 100644 index 0000000..f78b46e --- /dev/null +++ b/devicetypes/smartthings/zwave-siren.src/.st-ignore @@ -0,0 +1,2 @@ +.st-ignore +README.md diff --git a/devicetypes/smartthings/zwave-siren.src/README.md b/devicetypes/smartthings/zwave-siren.src/README.md new file mode 100644 index 0000000..ed17b1e --- /dev/null +++ b/devicetypes/smartthings/zwave-siren.src/README.md @@ -0,0 +1,42 @@ +# Z-wave Siren + +Cloud Execution + +Works with: + +* [FortrezZ Siren Strobe Alarm](https://www.smartthings.com/works-with-smartthings/other/fortrezz-water-valve) + +## Table of contents + +* [Capabilities](#capabilities) +* [Health](#device-health) +* [Troubleshooting](#troubleshooting) + +## Capabilities + +* **Actuator** - represents that a Device has commands +* **Alarm** - allows for interacting with devices that serve as alarms +* **Battery** - defines device uses a battery +* **Health Check** - indicates ability to get device health notifications +* **Polling** - represents that poll() can be implemented for the device +* **Refresh** - _refresh()_ command for status updates +* **Sensor** - detects sensor events +* **Switch** - can detect state (possible values: on/off) + +## Device Health + +FortrezZ Siren Strobe Alarm is polled by the hub. +As of hubCore version 0.14.38 the hub sends up reports every 15 minutes regardless of whether the state changed. +Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*15 + 2)mins = 32 mins. +Not to mention after going OFFLINE when the device is plugged back in, it might take a considerable amount of time for +the device to appear as ONLINE again. This is because if this listening device does not respond to two poll requests in a row, +it is not polled for 5 minutes by the hub. This can delay up the process of being marked ONLINE by quite some time. + +* __32min__ checkInterval + +## Troubleshooting + +If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range. +Pairing needs to be tried again by placing the device closer to the hub. +Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link: +* [FortrezZ Siren Strobe Alarm Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/202294760-FortrezZ-Siren-Strobe-Alarm) \ No newline at end of file diff --git a/devicetypes/smartthings/zwave-siren.src/zwave-siren.groovy b/devicetypes/smartthings/zwave-siren.src/zwave-siren.groovy index 9ee8071..d368610 100644 --- a/devicetypes/smartthings/zwave-siren.src/zwave-siren.groovy +++ b/devicetypes/smartthings/zwave-siren.src/zwave-siren.groovy @@ -20,6 +20,7 @@ metadata { capability "Actuator" capability "Alarm" capability "Battery" + capability "Health Check" capability "Polling" capability "Refresh" capability "Sensor" @@ -27,6 +28,7 @@ metadata { fingerprint inClusters: "0x20,0x25,0x86,0x80,0x85,0x72,0x71" + fingerprint mfr:"0084", prod:"0313", model:"010B", deviceJoinName: "FortrezZ Siren Strobe Alarm" } simulator { @@ -58,6 +60,11 @@ metadata { } } +def updated(){ +// Device-Watch simply pings if no device events received for 32min(checkInterval) + sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) +} + def createEvents(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) { def map = [ name: "battery", unit: "%" ] if (cmd.batteryLevel == 0xFF) { @@ -119,6 +126,13 @@ def both() { on() } +/** + * PING is used by Device-Watch in attempt to reach the Device + * */ +def ping() { + refresh() +} + def refresh() { log.debug "sending battery refresh command" zwave.batteryV1.batteryGet().format() diff --git a/devicetypes/smartthings/zwave-smoke-alarm.src/.st-ignore b/devicetypes/smartthings/zwave-smoke-alarm.src/.st-ignore new file mode 100644 index 0000000..f78b46e --- /dev/null +++ b/devicetypes/smartthings/zwave-smoke-alarm.src/.st-ignore @@ -0,0 +1,2 @@ +.st-ignore +README.md diff --git a/devicetypes/smartthings/zwave-smoke-alarm.src/README.md b/devicetypes/smartthings/zwave-smoke-alarm.src/README.md new file mode 100644 index 0000000..846990c --- /dev/null +++ b/devicetypes/smartthings/zwave-smoke-alarm.src/README.md @@ -0,0 +1,40 @@ +# Z-wave Smoke Alarm + +Cloud Execution + +Works with: + +* [First Alert Smoke Detector and Carbon Monoxide Alarm (ZCOMBO)](https://www.smartthings.com/works-with-smartthings/sensors/first-alert-smoke-detector-and-carbon-monoxide-alarm-zcombo) + +## Table of contents + +* [Capabilities](#capabilities) +* [Health](#device-health) +* [Battery](#battery-specification) +* [Troubleshooting](#troubleshooting) + +## Capabilities + +* **Smoke Detector** - measure smoke and optionally carbon monoxide levels +* **Carbon Monoxide Detector** - measure carbon monoxide levels +* **Sensor** - detects sensor events +* **Battery** - defines device uses a battery +* **Health Check** - indicates ability to get device health notifications + +## Device Health + +First Alert Smoke Detector and Carbon Monoxide Alarm (ZCOMBO) is a Z-wave sleepy device and checks in every 1 hour. +Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*60 + 2)mins = 122 mins. + +* __122min__ checkInterval + +## Battery Specification + +Two AA 1.5V batteries are required. + +## Troubleshooting + +If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range. +Pairing needs to be tried again by placing the device closer to the hub. +Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link: +* [First Alert Smoke Detector and Carbon Monoxide Alarm (ZCOMBO) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/201581984-First-Alert-Smoke-Detector-and-Carbon-Monoxide-Alarm-ZCOMBO-) \ No newline at end of file diff --git a/devicetypes/smartthings/zwave-smoke-alarm.src/zwave-smoke-alarm.groovy b/devicetypes/smartthings/zwave-smoke-alarm.src/zwave-smoke-alarm.groovy index aa426e4..f644386 100644 --- a/devicetypes/smartthings/zwave-smoke-alarm.src/zwave-smoke-alarm.groovy +++ b/devicetypes/smartthings/zwave-smoke-alarm.src/zwave-smoke-alarm.groovy @@ -17,10 +17,12 @@ metadata { capability "Carbon Monoxide Detector" capability "Sensor" capability "Battery" + capability "Health Check" attribute "alarmState", "string" fingerprint deviceId: "0xA100", inClusters: "0x20,0x80,0x70,0x85,0x71,0x72,0x86" + fingerprint mfr:"0138", prod:"0001", model:"0002", deviceJoinName: "First Alert Smoke Detector and Carbon Monoxide Alarm (ZCOMBO)" } simulator { @@ -51,6 +53,11 @@ metadata { } } +def updated(){ +// Device checks in every hour, this interval allows us to miss one check-in notification before marking offline + sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) +} + def parse(String description) { def results = [] if (description.startsWith("Err")) { @@ -65,7 +72,6 @@ def parse(String description) { return results } - def createSmokeOrCOEvents(name, results) { def text = null switch (name) { diff --git a/devicetypes/smartthings/zwave-switch-generic.src/README.md b/devicetypes/smartthings/zwave-switch-generic.src/README.md index baec4dd..f3fc268 100644 --- a/devicetypes/smartthings/zwave-switch-generic.src/README.md +++ b/devicetypes/smartthings/zwave-switch-generic.src/README.md @@ -1,4 +1,4 @@ -# Z-wave Switch +# Z-wave Switch Generic Cloud Execution @@ -8,6 +8,9 @@ Works with: * [GE Plug-In Outdoor Smart Switch (GE 12720) (Z-Wave)](https://www.smartthings.com/works-with-smartthings/outlets/ge-plug-in-outdoor-smart-switch) * [Leviton Outlet (DZR15-1LZ)](https://www.smartthings.com/works-with-smartthings/outlets/leviton-outlet) * [Leviton Switch (DZS15-1LZ)](https://www.smartthings.com/works-with-smartthings/switches-and-dimmers/leviton-switch) +* [Leviton 15A Switch (VRS15-1LZ)](https://www.smartthings.com/works-with-smartthings/lighting-and-switches/leviton-15a-switch) +* [Enerwave Duplex Receptacle (ZW15R)](https://www.smartthings.com/works-with-smartthings/outlets/enerwave-duplex-receptacle) +* [Enerwave On/Off Switch (ZW15S)](https://www.smartthings.com/works-with-smartthings/lighting-and-switches/enerwave-onoff-switch) ## Table of contents @@ -25,7 +28,7 @@ Works with: ## Device Health -Leviton Appliance Module (DZPA1-1LW), GE Plug-In Outdoor Smart Switch (GE 12720), Leviton Outlet (DZR15-1LZ) and Leviton Switch (DZS15-1LZ) (Z-Wave) are polled by the hub. +Leviton Appliance Module (DZPA1-1LW), GE Plug-In Outdoor Smart Switch (GE 12720), Leviton Outlet (DZR15-1LZ), Leviton Switch (DZS15-1LZ) (Z-Wave), Leviton Switch, Enerwave Duplex Receptacle (ZW15R) and Enerwave On/Off Switch (ZW15S) are polled by the hub. As of hubCore version 0.14.38 the hub sends up reports every 15 minutes regardless of whether the state changed. Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*15 + 2)mins = 32 mins. Not to mention after going OFFLINE when the device is plugged back in, it might take a considerable amount of time for @@ -42,4 +45,7 @@ Instructions related to pairing, resetting and removing the device from SmartThi * [Leviton Appliance Module (DZPA1-1LW) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206171053-How-to-connect-Leviton-Z-Wave-devices) * [GE Plug-In Outdoor Smart Switch (GE 12720) (Z-Wave) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/200903080-GE-Plug-In-Outdoor-Smart-Switch-GE-12720-Z-Wave-) * [Leviton Outlet (DZR15-1LZ) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206171053-How-to-connect-Leviton-Z-Wave-devices) -* [Leviton Switch (DZS15-1LZ) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206171053-How-to-connect-Leviton-Z-Wave-devices) \ No newline at end of file +* [Leviton Switch (DZS15-1LZ) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206171053-How-to-connect-Leviton-Z-Wave-devices) +* [Leviton 15A Switch (VRS15-1LZ) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206171053-How-to-connect-Leviton-Z-Wave-devices) +* [Enerwave Duplex Receptacle (ZW15R) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/204854176-How-to-connect-Enerwave-switches-and-dimmers) +* [Enerwave On/Off Switch (ZW15S) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/204854176-How-to-connect-Enerwave-switches-and-dimmers) \ No newline at end of file diff --git a/devicetypes/smartthings/zwave-switch-generic.src/zwave-switch-generic.groovy b/devicetypes/smartthings/zwave-switch-generic.src/zwave-switch-generic.groovy index 01ce695..ced18ce 100644 --- a/devicetypes/smartthings/zwave-switch-generic.src/zwave-switch-generic.groovy +++ b/devicetypes/smartthings/zwave-switch-generic.src/zwave-switch-generic.groovy @@ -19,12 +19,18 @@ metadata { capability "Polling" capability "Refresh" capability "Sensor" + capability "Light" fingerprint inClusters: "0x25", deviceJoinName: "Z-Wave Switch" fingerprint mfr:"001D", prod:"1A02", model:"0334", deviceJoinName: "Leviton Appliance Module" fingerprint mfr:"0063", prod:"4F50", model:"3031", deviceJoinName: "GE Plug-in Outdoor Switch" fingerprint mfr:"001D", prod:"1D04", model:"0334", deviceJoinName: "Leviton Outlet" fingerprint mfr:"001D", prod:"1C02", model:"0334", deviceJoinName: "Leviton Switch" + fingerprint mfr:"001D", prod:"0301", model:"0334", deviceJoinName: "Leviton 15A Switch" + fingerprint mfr:"001D", prod:"0F01", model:"0334", deviceJoinName: "Leviton 5A Incandescent Switch" + fingerprint mfr:"001D", prod:"1603", model:"0334", deviceJoinName: "Leviton 15A Split Duplex Receptacle" + fingerprint mfr:"011A", prod:"0101", model:"0102", deviceJoinName: "Enerwave On/Off Switch" + fingerprint mfr:"011A", prod:"0101", model:"0603", deviceJoinName: "Enerwave Duplex Receptacle" } // simulator metadata @@ -41,7 +47,7 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" + attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC" attributeState "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" } } diff --git a/devicetypes/smartthings/zwave-switch-secure.src/zwave-switch-secure.groovy b/devicetypes/smartthings/zwave-switch-secure.src/zwave-switch-secure.groovy index c35ebc0..a5a1dc1 100644 --- a/devicetypes/smartthings/zwave-switch-secure.src/zwave-switch-secure.groovy +++ b/devicetypes/smartthings/zwave-switch-secure.src/zwave-switch-secure.groovy @@ -33,7 +33,7 @@ metadata { tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { - state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" + state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00a0dc" state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" } standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") { diff --git a/devicetypes/smartthings/zwave-switch.src/zwave-switch.groovy b/devicetypes/smartthings/zwave-switch.src/zwave-switch.groovy index ac0f46d..b7c7106 100644 --- a/devicetypes/smartthings/zwave-switch.src/zwave-switch.groovy +++ b/devicetypes/smartthings/zwave-switch.src/zwave-switch.groovy @@ -20,6 +20,7 @@ metadata { capability "Refresh" capability "Sensor" capability "Health Check" + capability "Light" fingerprint mfr:"0063", prod:"4952", deviceJoinName: "Z-Wave Wall Switch" fingerprint mfr:"0063", prod:"5257", deviceJoinName: "Z-Wave Wall Switch" @@ -45,7 +46,7 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" + attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC" attributeState "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" } } diff --git a/devicetypes/smartthings/zwave-thermostat.src/zwave-thermostat.groovy b/devicetypes/smartthings/zwave-thermostat.src/zwave-thermostat.groovy index 404882a..8d9f117 100644 --- a/devicetypes/smartthings/zwave-thermostat.src/zwave-thermostat.groovy +++ b/devicetypes/smartthings/zwave-thermostat.src/zwave-thermostat.groovy @@ -20,6 +20,7 @@ metadata { capability "Configuration" capability "Polling" capability "Sensor" + capability "Health Check" attribute "thermostatFanState", "string" @@ -30,6 +31,7 @@ metadata { fingerprint deviceId: "0x08" fingerprint inClusters: "0x43,0x40,0x44,0x31" + fingerprint mfr:"0039", prod:"0011", model:"0001", deviceJoinName: "Honeywell Z-Wave Thermostat" } // simulator metadata @@ -123,6 +125,11 @@ metadata { } } +def updated(){ + // Device-Watch simply pings if no device events received for 32min(checkInterval) + sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) +} + def parse(String description) { def map = createEvent(zwaveEvent(zwave.parse(description, [0x42:1, 0x43:2, 0x31: 3]))) @@ -393,6 +400,14 @@ def setCoolingSetpoint(Double degrees, Integer delay = 30000) { ], delay) } +/** + * PING is used by Device-Watch in attempt to reach the Device + * */ +def ping() { + log.debug "ping() called" + poll() +} + def configure() { delayBetween([ zwave.thermostatModeV2.thermostatModeSupportedGet().format(), diff --git a/devicetypes/smartthings/zwave-virtual-momentary-contact-switch.src/zwave-virtual-momentary-contact-switch.groovy b/devicetypes/smartthings/zwave-virtual-momentary-contact-switch.src/zwave-virtual-momentary-contact-switch.groovy index ac54c9a..5f4db51 100644 --- a/devicetypes/smartthings/zwave-virtual-momentary-contact-switch.src/zwave-virtual-momentary-contact-switch.groovy +++ b/devicetypes/smartthings/zwave-virtual-momentary-contact-switch.src/zwave-virtual-momentary-contact-switch.groovy @@ -39,7 +39,7 @@ metadata { tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { state "off", label: '${name}', action: "momentary.push", icon: "st.switches.switch.off", backgroundColor: "#ffffff" - state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" + state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00a0dc" } standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") { state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh" diff --git a/devicetypes/smartthings/zwave-water-sensor.src/zwave-water-sensor.groovy b/devicetypes/smartthings/zwave-water-sensor.src/zwave-water-sensor.groovy index 7f50063..bd867b9 100644 --- a/devicetypes/smartthings/zwave-water-sensor.src/zwave-water-sensor.groovy +++ b/devicetypes/smartthings/zwave-water-sensor.src/zwave-water-sensor.groovy @@ -33,7 +33,7 @@ metadata { tiles { standardTile("water", "device.water", width: 2, height: 2) { state "dry", icon:"st.alarm.water.dry", backgroundColor:"#ffffff" - state "wet", icon:"st.alarm.water.wet", backgroundColor:"#53a7c0" + state "wet", icon:"st.alarm.water.wet", backgroundColor:"#00A0DC" } valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") { state "battery", label:'${currentValue}% battery', unit:"" diff --git a/devicetypes/smartthings/zwave-water-valve.src/zwave-water-valve.groovy b/devicetypes/smartthings/zwave-water-valve.src/zwave-water-valve.groovy index 0be843d..8826760 100644 --- a/devicetypes/smartthings/zwave-water-valve.src/zwave-water-valve.groovy +++ b/devicetypes/smartthings/zwave-water-valve.src/zwave-water-valve.groovy @@ -36,10 +36,10 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"valve", type: "generic", width: 6, height: 4, canChangeIcon: true){ tileAttribute ("device.contact", key: "PRIMARY_CONTROL") { - attributeState "open", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#53a7c0", nextState:"closing" - attributeState "closed", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#e86d13", nextState:"opening" - attributeState "opening", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#ffe71e" - attributeState "closing", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#ffe71e" + attributeState "open", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#00A0DC", nextState:"closing" + attributeState "closed", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#ffffff", nextState:"opening" + attributeState "opening", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#00A0DC" + attributeState "closing", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#ffffff" } } diff --git a/devicetypes/timevalve-gaslock-t-08/timevalve-smart.src/timevalve-smart.groovy b/devicetypes/timevalve-gaslock-t-08/timevalve-smart.src/timevalve-smart.groovy index 53df65a..feca26e 100644 --- a/devicetypes/timevalve-gaslock-t-08/timevalve-smart.src/timevalve-smart.groovy +++ b/devicetypes/timevalve-gaslock-t-08/timevalve-smart.src/timevalve-smart.groovy @@ -25,12 +25,12 @@ metadata { tiles (scale: 2) { multiAttributeTile(name:"statusTile", type:"generic", width:6, height:4) { tileAttribute("device.contact", key: "PRIMARY_CONTROL") { - attributeState "open", label: '${name}', action: "close", icon:"st.contact.contact.open", backgroundColor:"#ffa81e" - attributeState "closed", label:'${name}', action: "", icon:"st.contact.contact.closed", backgroundColor:"#79b821" + attributeState "open", label: '${name}', action: "close", icon:"st.contact.contact.open", backgroundColor:"#e86d13" + attributeState "closed", label:'${name}', action: "", icon:"st.contact.contact.closed", backgroundColor:"#00a0dc" } tileAttribute("device.remainingText", key: "SECONDARY_CONTROL") { - attributeState "open", label: '${currentValue}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e" - attributeState "closed", label:'', icon:"st.contact.contact.closed", backgroundColor:"#79b821" + attributeState "open", label: '${currentValue}', icon:"st.contact.contact.open", backgroundColor:"#e86d13" + attributeState "closed", label:'', icon:"st.contact.contact.closed", backgroundColor:"#00a0dc" } } diff --git a/devicetypes/vlaminck/minecraft/smart-block.src/smart-block.groovy b/devicetypes/vlaminck/minecraft/smart-block.src/smart-block.groovy index d5ec4c0..f17a4cf 100644 --- a/devicetypes/vlaminck/minecraft/smart-block.src/smart-block.groovy +++ b/devicetypes/vlaminck/minecraft/smart-block.src/smart-block.groovy @@ -39,8 +39,8 @@ metadata { tiles { standardTile("switch", "device.switch", width: 1, height: 1, canChangeIcon: true) { state "off", label: '${name}', icon: "st.switches.switch.off", backgroundColor: "#ffffff", action: "switch.on", nextState: "turningOn" - state "turningOn", label: '${name}', icon: "st.switches.switch.on", backgroundColor: "#79b821" - state "on", label: '${name}', icon: "st.switches.switch.on", backgroundColor: "#79b821", action: "switch.off", nextState: "turningOff" + state "turningOn", label: '${name}', icon: "st.switches.switch.on", backgroundColor: "#00A0DC" + state "on", label: '${name}', icon: "st.switches.switch.on", backgroundColor: "#00A0DC", action: "switch.off", nextState: "turningOff" state "turningOff", label: '${name}', icon: "st.switches.switch.off", backgroundColor: "#ffffff" } valueTile("level", "device.level", height: 1, width: 1, inactiveLabel: false) { diff --git a/devicetypes/wackford/quirky-wink-eggtray.src/quirky-wink-eggtray.groovy b/devicetypes/wackford/quirky-wink-eggtray.src/quirky-wink-eggtray.groovy index 9e8ea7f..4d9d00c 100644 --- a/devicetypes/wackford/quirky-wink-eggtray.src/quirky-wink-eggtray.groovy +++ b/devicetypes/wackford/quirky-wink-eggtray.src/quirky-wink-eggtray.groovy @@ -53,15 +53,15 @@ metadata { tiles { standardTile("inventory", "device.inventory", width: 2, height: 2){ - state "goodEggs", label : " ", unit : "" , icon:"st.quirky.egg-minder.quirky-egg-device", backgroundColor: "#53a7c0" - state "haveBadEgg", label : " ", unit : "" , icon:"st.quirky.egg-minder.quirky-egg-device", backgroundColor: "#FF1919" + state "goodEggs", label : " ", unit : "" , icon:"st.quirky.egg-minder.quirky-egg-device", backgroundColor: "#00A0DC" + state "haveBadEgg", label : " ", unit : "" , icon:"st.quirky.egg-minder.quirky-egg-device", backgroundColor: "#e86d13" state "noEggs", label : " ", unit : "" , icon:"st.quirky.egg-minder.quirky-egg-device", backgroundColor: "#ffffff" } standardTile("totalEggs", "device.totalEggs", inactiveLabel: false){ state "totalEggs", label : '${currentValue}', unit : "" , icon:"st.quirky.egg-minder.quirky-egg-count", backgroundColor: "#53a7c0" } standardTile("freshEggs", "device.freshEggs", inactiveLabel: false){ - state "freshEggs", label : '${currentValue}', unit : "" , icon:"st.quirky.egg-minder.quirky-egg-fresh", backgroundColor: "#53a7c0" + state "freshEggs", label : '${currentValue}', unit : "" , icon:"st.quirky.egg-minder.quirky-egg-fresh", backgroundColor: "#00A0DC" } standardTile("oldEggs", "device.oldEggs", inactiveLabel: false){ state "oldEggs", label : '${currentValue}', unit : "" , icon:"st.quirky.egg-minder.quirky-egg-expired", backgroundColor: "#53a7c0" diff --git a/devicetypes/wackford/quirky-wink-porkfolio.src/quirky-wink-porkfolio.groovy b/devicetypes/wackford/quirky-wink-porkfolio.src/quirky-wink-porkfolio.groovy index 8bf827b..4765be9 100644 --- a/devicetypes/wackford/quirky-wink-porkfolio.src/quirky-wink-porkfolio.groovy +++ b/devicetypes/wackford/quirky-wink-porkfolio.src/quirky-wink-porkfolio.groovy @@ -45,8 +45,8 @@ metadata { tiles { standardTile("acceleration", "device.acceleration", width: 2, height: 2, canChangeIcon: true) { - state "inactive", label:'pig secure', icon:"st.motion.acceleration.inactive", backgroundColor:"#44b621" - state "active", label:'pig alarm', icon:"st.motion.acceleration.active", backgroundColor:"#FF1919" + state "inactive", label:'pig secure', icon:"st.motion.acceleration.inactive", backgroundColor:"#cccccc" + state "active", label:'pig alarm', icon:"st.motion.acceleration.active", backgroundColor:"#00A0DC" } standardTile("balance", "device.balance", inactiveLabel: false, canChangeIcon: true) { state "balance", label:'${currentValue}', unit:"", icon:"st.Food & Dining.dining18" diff --git a/devicetypes/wackford/quirky-wink-powerstrip.src/quirky-wink-powerstrip.groovy b/devicetypes/wackford/quirky-wink-powerstrip.src/quirky-wink-powerstrip.groovy index 8dd6c27..b4b38bf 100644 --- a/devicetypes/wackford/quirky-wink-powerstrip.src/quirky-wink-powerstrip.groovy +++ b/devicetypes/wackford/quirky-wink-powerstrip.src/quirky-wink-powerstrip.groovy @@ -46,7 +46,7 @@ metadata { tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" - state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" + state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC" } standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat") { state "default", action:"refresh.refresh", icon:"st.secondary.refresh" diff --git a/devicetypes/wackford/quirky-wink-spotter.src/quirky-wink-spotter.groovy b/devicetypes/wackford/quirky-wink-spotter.src/quirky-wink-spotter.groovy index 8de12f2..5133606 100644 --- a/devicetypes/wackford/quirky-wink-spotter.src/quirky-wink-spotter.groovy +++ b/devicetypes/wackford/quirky-wink-spotter.src/quirky-wink-spotter.groovy @@ -54,8 +54,8 @@ metadata { tiles { standardTile("acceleration", "device.acceleration", width: 2, height: 2, canChangeIcon: true) { - state "active", label:'active', icon:"st.motion.acceleration.active", backgroundColor:"#53a7c0" - state "inactive", label:'inactive', icon:"st.motion.acceleration.inactive", backgroundColor:"#ffffff" + state "active", label:'active', icon:"st.motion.acceleration.active", backgroundColor:"#00A0DC" + state "inactive", label:'inactive', icon:"st.motion.acceleration.inactive", backgroundColor:"#cccccc" } valueTile("temperature", "device.temperature", canChangeIcon: false) { @@ -75,11 +75,11 @@ metadata { state "humidity", label:'${currentValue}% RH', unit:"" } standardTile("sound", "device.sound", inactiveLabel: false) { - state "active", label: "noise", unit:"", icon: "st.alarm.beep.beep", backgroundColor: "#53a7c0" - state "inactive", label: "quiet", unit:"", icon: "st.alarm.beep.beep", backgroundColor: "#ffffff" + state "active", label: "noise", unit:"", icon: "st.alarm.beep.beep", backgroundColor: "#00A0DC" + state "inactive", label: "quiet", unit:"", icon: "st.alarm.beep.beep", backgroundColor: "#cccccc" } standardTile("light", "device.light", inactiveLabel: false, canChangeIcon: true) { - state "active", label: "light", unit:"", icon: "st.illuminance.illuminance.bright", backgroundColor: "#53a7c0" + state "active", label: "light", unit:"", icon: "st.illuminance.illuminance.bright", backgroundColor: "#00A0DC" state "inactive", label: "dark", unit:"", icon: "st.illuminance.illuminance.dark", backgroundColor: "#B2B2B2" } valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false, canChangeIcon: false) { diff --git a/devicetypes/wackford/tcp-bulb.src/tcp-bulb.groovy b/devicetypes/wackford/tcp-bulb.src/tcp-bulb.groovy index 186c8b2..124808a 100644 --- a/devicetypes/wackford/tcp-bulb.src/tcp-bulb.groovy +++ b/devicetypes/wackford/tcp-bulb.src/tcp-bulb.groovy @@ -70,9 +70,9 @@ metadata { tiles { standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { - state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" + state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff" state "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" - state "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" + state "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff" state "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" } controlTile("levelSliderControl", "device.level", "slider", height: 1, width: 2, inactiveLabel: false) { diff --git a/devicetypes/zenwithin/zen-thermostat.src/zen-thermostat.groovy b/devicetypes/zenwithin/zen-thermostat.src/zen-thermostat.groovy index a13646f..2e046da 100644 --- a/devicetypes/zenwithin/zen-thermostat.src/zen-thermostat.groovy +++ b/devicetypes/zenwithin/zen-thermostat.src/zen-thermostat.groovy @@ -36,7 +36,7 @@ metadata { } valueTile("temperature", "device.temperature", width: 1, height: 1) { - state("temperature", label:'${currentValue}°', backgroundColor:"#0A1E2C") + state("temperature", label:'${currentValue}°', backgroundColor:"#00A0DC") } standardTile("fanMode", "device.thermostatFanMode", decoration: "flat") { @@ -46,9 +46,9 @@ metadata { standardTile("mode", "device.thermostatMode", decoration: "flat") { - state "off", action:"setThermostatMode", backgroundColor:"#e8e3d8", icon:"st.thermostat.heating-cooling-off", nextState:"heating" - state "heat", action:"setThermostatMode", backgroundColor:"#ff6e7e", icon:"st.thermostat.heat", nextState:"cooling" - state "cool", action:"setThermostatMode", backgroundColor:"#90d0e8", icon:"st.thermostat.cool", nextState:"..." + state "off", action:"setThermostatMode", backgroundColor:"#ffffff", icon:"st.thermostat.heating-cooling-off", nextState:"heating" + state "heat", action:"setThermostatMode", backgroundColor:"#e86d13", icon:"st.thermostat.heat", nextState:"cooling" + state "cool", action:"setThermostatMode", backgroundColor:"#00A0DC", icon:"st.thermostat.cool", nextState:"..." //state "auto", action:"setThermostatMode", backgroundColor:"#e8e3d8", icon:"st.thermostat.auto" state "heating", action:"setThermostatMode", nextState:"to_cool" state "cooling", action:"setThermostatMode", nextState:"..." diff --git a/smartapps/dianoga/netatmo-connect.src/netatmo-connect.groovy b/smartapps/dianoga/netatmo-connect.src/netatmo-connect.groovy index 65ed151..3a7d663 100644 --- a/smartapps/dianoga/netatmo-connect.src/netatmo-connect.groovy +++ b/smartapps/dianoga/netatmo-connect.src/netatmo-connect.groovy @@ -5,7 +5,6 @@ import java.text.DecimalFormat import groovy.json.JsonSlurper private getApiUrl() { "https://api.netatmo.com" } -private getVendorName() { "netatmo" } private getVendorAuthPath() { "${apiUrl}/oauth2/authorize?" } private getVendorTokenPath(){ "${apiUrl}/oauth2/token" } private getVendorIcon() { "https://s3.amazonaws.com/smartapp-icons/Partner/netamo-icon-1%402x.png" } @@ -14,14 +13,13 @@ private getClientSecret() { appSettings.clientSecret } private getServerUrl() { appSettings.serverUrl } private getShardUrl() { return getApiServerUrl() } private getCallbackUrl() { "${serverUrl}/oauth/callback" } -private getBuildRedirectUrl() { "${serverUrl}/oauth/initialize?appId=${app.id}&access_token=${state.accessToken}&apiServerUrl=${shardUrl}" } +private getBuildRedirectUrl() { "${serverUrl}/oauth/initialize?appId=${app.id}&access_token=${atomicState.accessToken}&apiServerUrl=${shardUrl}" } -// Automatically generated. Make future change here. definition( name: "Netatmo (Connect)", namespace: "dianoga", author: "Brian Steere", - description: "Netatmo Integration", + description: "Integrate your Netatmo devices with SmartThings", category: "SmartThings Labs", iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/netamo-icon-1.png", iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/netamo-icon-1%402x.png", @@ -44,15 +42,16 @@ mappings { } def authPage() { - log.debug "In authPage" + // log.debug "running authPage()" def description def uninstallAllowed = false def oauthTokenProvided = false - if (!state.accessToken) { - log.debug "About to create access token." - state.accessToken = createAccessToken() + // If an access token doesn't exist, create one + if (!atomicState.accessToken) { + atomicState.accessToken = createAccessToken() + log.debug "Created access token" } if (canInstallLabs()) { @@ -60,36 +59,32 @@ def authPage() { def redirectUrl = getBuildRedirectUrl() // log.debug "Redirect url = ${redirectUrl}" - if (state.authToken) { - description = "Tap 'Next' to proceed" + if (atomicState.authToken) { + description = "Tap 'Next' to select devices" uninstallAllowed = true oauthTokenProvided = true } else { - description = "Click to enter Credentials." + description = "Tap to enter credentials" } if (!oauthTokenProvided) { - log.debug "Show the login page" + log.debug "Showing the login page" return dynamicPage(name: "Credentials", title: "Authorize Connection", nextPage:"listDevices", uninstall: uninstallAllowed, install:false) { section() { - paragraph "Tap below to log in to the netatmo and authorize SmartThings access." - href url:redirectUrl, style:"embedded", required:false, title:"Connect to ${getVendorName()}:", description:description + paragraph "Tap below to login to Netatmo and authorize SmartThings access" + href url:redirectUrl, style:"embedded", required:false, title:"Connect to Netatmo", description:description } } } else { - log.debug "Show the devices page" - return dynamicPage(name: "Credentials", title: "Credentials Accepted!", nextPage:"listDevices", uninstall: uninstallAllowed, install:false) { + log.debug "Showing the devices page" + return dynamicPage(name: "Credentials", title: "Connected", nextPage:"listDevices", uninstall: uninstallAllowed, install:false) { section() { - input(name:"Devices", style:"embedded", required:false, title:"${getVendorName()} is now connected to SmartThings!", description:description) + input(name:"Devices", style:"embedded", required:false, title:"Netatmo is connected to SmartThings", description:description) } } } } else { - def upgradeNeeded = """To use SmartThings Labs, your Hub should be completely up to date. - -To update your Hub, access Location Settings in the Main Menu (tap the gear next to your location name), select your Hub, and choose "Update Hub".""" - - + def upgradeNeeded = """To use SmartThings Labs, your Hub should be completely up to date. To update your Hub, access Location Settings in the Main Menu (tap the gear next to your location name), select your Hub, and choose "Update Hub".""" return dynamicPage(name:"Credentials", title:"Upgrade needed!", nextPage:"", install:false, uninstall: true) { section { paragraph "$upgradeNeeded" @@ -100,15 +95,15 @@ To update your Hub, access Location Settings in the Main Menu (tap the gear next } def oauthInitUrl() { - log.debug "In oauthInitUrl" + // log.debug "runing oauthInitUrl()" - state.oauthInitState = UUID.randomUUID().toString() + atomicState.oauthInitState = UUID.randomUUID().toString() def oauthParams = [ response_type: "code", client_id: getClientId(), client_secret: getClientSecret(), - state: state.oauthInitState, + state: atomicState.oauthInitState, redirect_uri: getCallbackUrl(), scope: "read_station" ] @@ -119,73 +114,72 @@ def oauthInitUrl() { } def callback() { - // log.debug "callback()>> params: $params, params.code ${params.code}" + // log.debug "running callback()" def code = params.code def oauthState = params.state - if (oauthState == state.oauthInitState) { + if (oauthState == atomicState.oauthInitState) { def tokenParams = [ + grant_type: "authorization_code", client_secret: getClientSecret(), client_id : getClientId(), - grant_type: "authorization_code", - redirect_uri: getCallbackUrl(), code: code, - scope: "read_station" + scope: "read_station", + redirect_uri: getCallbackUrl() ] // log.debug "TOKEN URL: ${getVendorTokenPath() + toQueryString(tokenParams)}" def tokenUrl = getVendorTokenPath() - def params = [ + def requestTokenParams = [ uri: tokenUrl, - contentType: 'application/x-www-form-urlencoded', + requestContentType: 'application/x-www-form-urlencoded', body: tokenParams ] + + // log.debug "PARAMS: ${requestTokenParams}" - // log.debug "PARAMS: ${params}" + try { + httpPost(requestTokenParams) { resp -> + //log.debug "Data: ${resp.data}" + atomicState.refreshToken = resp.data.refresh_token + atomicState.authToken = resp.data.access_token + // resp.data.expires_in is in milliseconds so we need to convert it to seconds + atomicState.tokenExpires = now() + (resp.data.expires_in * 1000) + } + } catch (e) { + log.debug "callback() failed: $e" + } - httpPost(params) { resp -> - - def slurper = new JsonSlurper() - - resp.data.each { key, value -> - def data = slurper.parseText(key) - - state.refreshToken = data.refresh_token - state.authToken = data.access_token - state.tokenExpires = now() + (data.expires_in * 1000) - // log.debug "swapped token: $resp.data" - } - } - - // Handle success and failure here, and render stuff accordingly - if (state.authToken) { + // If we successfully got an authToken run sucess(), else fail() + if (atomicState.authToken) { success() } else { fail() } } else { - log.error "callback() failed oauthState != state.oauthInitState" + log.error "callback() failed oauthState != atomicState.oauthInitState" } } def success() { - log.debug "in success" + log.debug "OAuth flow succeeded" def message = """ -

We have located your """ + getVendorName() + """ account.

-

Tap 'Done' to continue to Devices.

+

Success!

+

Tap 'Done' to continue

""" connectionStatus(message) } def fail() { - log.debug "in fail" + log.debug "OAuth flow failed" + atomicState.authToken = null def message = """ -

The connection could not be established!

-

Click 'Done' to return to the menu.

+

Error

+

Tap 'Done' to return

""" connectionStatus(message) } @@ -197,13 +191,12 @@ def connectionStatus(message, redirectUrl = null) { """ } - def html = """ - ${getVendorName()} Connection + Netatmo Connection @@ -269,46 +256,47 @@ def connectionStatus(message, redirectUrl = null) { } def refreshToken() { - log.debug "In refreshToken" + // Check if atomicState has a refresh token + if (atomicState.refreshToken) { + log.debug "running refreshToken()" - def oauthParams = [ - client_secret: getClientSecret(), - client_id: getClientId(), - grant_type: "refresh_token", - refresh_token: state.refreshToken - ] + def oauthParams = [ + grant_type: "refresh_token", + refresh_token: atomicState.refreshToken, + client_secret: getClientSecret(), + client_id: getClientId(), + ] - def tokenUrl = getVendorTokenPath() - def params = [ - uri: tokenUrl, - contentType: 'application/x-www-form-urlencoded', - body: oauthParams, - ] + def tokenUrl = getVendorTokenPath() + + def requestOauthParams = [ + uri: tokenUrl, + requestContentType: 'application/x-www-form-urlencoded', + body: oauthParams + ] + + // log.debug "PARAMS: ${requestOauthParams}" - // OAuth Step 2: Request access token with our client Secret and OAuth "Code" - try { - httpPost(params) { response -> - def slurper = new JsonSlurper(); + try { + httpPost(requestOauthParams) { resp -> + //log.debug "Data: ${resp.data}" + atomicState.refreshToken = resp.data.refresh_token + atomicState.authToken = resp.data.access_token + // resp.data.expires_in is in milliseconds so we need to convert it to seconds + atomicState.tokenExpires = now() + (resp.data.expires_in * 1000) + return true + } + } catch (e) { + log.debug "refreshToken() failed: $e" + } - response.data.each {key, value -> - def data = slurper.parseText(key); - // log.debug "Data: $data" - - state.refreshToken = data.refresh_token - state.accessToken = data.access_token - state.tokenExpires = now() + (data.expires_in * 1000) - return true - } - - } - } catch (Exception e) { - log.debug "Error: $e" - } - - // We didn't get an access token - if ( !state.accessToken ) { - return false - } + // If we didn't get an authToken + if (!atomicState.authToken) { + return false + } + } else { + return false + } } String toQueryString(Map m) { @@ -317,13 +305,11 @@ String toQueryString(Map m) { def installed() { log.debug "Installed with settings: ${settings}" - initialize() } def updated() { log.debug "Updated with settings: ${settings}" - unsubscribe() unschedule() initialize() @@ -331,9 +317,9 @@ def updated() { def initialize() { log.debug "Initialized with settings: ${settings}" - + // Pull the latest device info into state - getDeviceList(); + getDeviceList() settings.devices.each { def deviceId = it @@ -367,57 +353,56 @@ def initialize() { def delete = getChildDevices().findAll { !settings.devices.contains(it.deviceNetworkId) } log.debug "Delete: $delete" delete.each { deleteChildDevice(it.deviceNetworkId) } - - // Do the initial poll + + // Run initial poll and schedule future polls poll() - // Schedule it to run every 5 minutes runEvery5Minutes("poll") } def uninstalled() { - log.debug "In uninstalled" - + log.debug "Uninstalling" removeChildDevices(getChildDevices()) } def getDeviceList() { - log.debug "In getDeviceList" + if (atomicState.authToken) { + + log.debug "Getting stations data" - def deviceList = [:] - state.deviceDetail = [:] - state.deviceState = [:] + def deviceList = [:] + state.deviceDetail = [:] + state.deviceState = [:] - apiGet("/api/devicelist") { response -> - response.data.body.devices.each { value -> - def key = value._id - deviceList[key] = "${value.station_name}: ${value.module_name}" - state.deviceDetail[key] = value - state.deviceState[key] = value.dashboard_data - } - response.data.body.modules.each { value -> - def key = value._id - deviceList[key] = "${state.deviceDetail[value.main_device].station_name}: ${value.module_name}" - state.deviceDetail[key] = value - state.deviceState[key] = value.dashboard_data - } - } - - return deviceList.sort() { it.value.toLowerCase() } + apiGet("/api/getstationsdata") { resp -> + resp.data.body.devices.each { value -> + def key = value._id + deviceList[key] = "${value.station_name}: ${value.module_name}" + state.deviceDetail[key] = value + state.deviceState[key] = value.dashboard_data + value.modules.each { value2 -> + def key2 = value2._id + deviceList[key2] = "${value.station_name}: ${value2.module_name}" + state.deviceDetail[key2] = value2 + state.deviceState[key2] = value2.dashboard_data + } + } + } + + return deviceList.sort() { it.value.toLowerCase() } + + } else { + return null + } } private removeChildDevices(delete) { - log.debug "In removeChildDevices" - - log.debug "deleting ${delete.size()} devices" - + log.debug "Removing ${delete.size()} devices" delete.each { deleteChildDevice(it.deviceNetworkId) } } def createChildDevice(deviceFile, dni, name, label) { - log.debug "In createChildDevice" - try { def existingDevice = getChildDevice(dni) if(!existingDevice) { @@ -432,13 +417,13 @@ def createChildDevice(deviceFile, dni, name, label) { } def listDevices() { - log.debug "In listDevices" + log.debug "Listing devices" def devices = getDeviceList() - dynamicPage(name: "listDevices", title: "Choose devices", install: true) { + dynamicPage(name: "listDevices", title: "Choose Devices", install: true) { section("Devices") { - input "devices", "enum", title: "Select Device(s)", required: false, multiple: true, options: devices + input "devices", "enum", title: "Select Devices", required: false, multiple: true, options: devices } section("Preferences") { @@ -448,30 +433,36 @@ def listDevices() { } def apiGet(String path, Map query, Closure callback) { - if(now() >= state.tokenExpires) { - refreshToken(); + log.debug "running apiGet()" + + // If the current time is over the expiration time, request a new token + if(now() >= atomicState.tokenExpires) { + atomicState.authToken = null + refreshToken() } - query['access_token'] = state.accessToken - def params = [ + def queryParam = [ + access_token: atomicState.authToken + ] + + def apiGetParams = [ uri: getApiUrl(), path: path, - 'query': query + query: queryParam ] - // log.debug "API Get: $params" + + // log.debug "apiGet(): $apiGetParams" try { - httpGet(params) { response -> - callback.call(response) + httpGet(apiGetParams) { resp -> + callback.call(resp) } - } catch (Exception e) { - // This is most likely due to an invalid token. Try to refresh it and try again. - log.debug "apiGet: Call failed $e" - if(refreshToken()) { - log.debug "apiGet: Trying again after refreshing token" - httpGet(params) { response -> - callback.call(response) - } + } catch (e) { + log.debug "apiGet() failed: $e" + // Netatmo API has rate limits so a failure here doesn't necessarily mean our token has expired, but we will check anyways + if(now() >= atomicState.tokenExpires) { + atomicState.authToken = null + refreshToken() } } } @@ -481,10 +472,12 @@ def apiGet(String path, Closure callback) { } def poll() { - log.debug "In Poll" - getDeviceList(); + log.debug "Polling..." + + getDeviceList() + def children = getChildDevices() - log.debug "State: ${state.deviceState}" + //log.debug "State: ${state.deviceState}" settings.devices.each { deviceId -> def detail = state?.deviceDetail[deviceId] @@ -540,15 +533,13 @@ def rainToPref(rain) { } def debugEvent(message, displayEvent) { - def results = [ name: "appdebug", descriptionText: message, displayed: displayEvent ] log.debug "Generating AppDebug Event: ${results}" - sendEvent (results) - + sendEvent(results) } private Boolean canInstallLabs() { @@ -561,4 +552,4 @@ private Boolean hasAllHubsOver(String desiredFirmware) { private List getRealHubFirmwareVersions() { return location.hubs*.firmwareVersionString.findAll { it } -} +} \ No newline at end of file diff --git a/smartapps/gideon-api/gideon-smart-home.src/gideon-smart-home.groovy b/smartapps/gideon-api/gideon-smart-home.src/gideon-smart-home.groovy new file mode 100644 index 0000000..a198d72 --- /dev/null +++ b/smartapps/gideon-api/gideon-smart-home.src/gideon-smart-home.groovy @@ -0,0 +1,794 @@ +/** + * Gideon + * + * Copyright 2016 Nicola Russo + * + * 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: "Gideon Smart Home", + namespace: "gideon.api", + author: "Braindrain Solutions ltd", + description: "Gideon Smart Home SmartApp allows you to connect and control all of your SmartThings devices through the Gideon app, making your SmartThings devices even smarter.", + category: "Family", + iconUrl: "http://s33.postimg.org/t77u7y7v3/logo.png", + iconX2Url: "http://s33.postimg.org/t77u7y7v3/logo.png", + iconX3Url: "http://s33.postimg.org/t77u7y7v3/logo.png", + oauth: [displayName: "Gideon Smart Home API app", displayLink: "gideon.ai"]) + +preferences { + section("Control these contact sensors...") { + input "contact", "capability.contactSensor", multiple:true, required:false + } + section("Control these switch levels...") { + input "switchlevels", "capability.switchLevel", multiple:true, required:false + } +/* section("Control these thermostats...") { + input "thermostats", "capability.thermostat", multiple:true, required:false + }*/ + section("Control the color for these devices...") { + input "colors", "capability.colorControl", multiple:true, required:false + } + section("Control the color temperature for these devices...") { + input "kelvin", "capability.colorTemperature", multiple:true, required:false + } + section("Control these switches...") { + input "switches", "capability.switch", multiple:true, required:false + } + section("Control these smoke alarms...") { + input "smoke_alarms", "capability.smokeDetector", multiple:true, required:false + } + section("Control these window shades...") { + input "shades", "capability.windowShade", multiple:true, required:false + } + section("Control these garage doors...") { + input "garage", "capability.garageDoorControl", multiple:true, required:false + } + section("Control these water sensors...") { + input "water_sensors", "capability.waterSensor", multiple:true, required:false + } + section("Control these motion sensors...") { + input "motions", "capability.motionSensor", multiple:true, required:false + } + section("Control these presence sensors...") { + input "presence_sensors", "capability.presenceSensor", multiple:true, required:false + } + section("Control these outlets...") { + input "outlets", "capability.outlet", multiple:true, required:false + } + section("Control these power meters...") { + input "meters", "capability.powerMeter", multiple:true, required:false + } + section("Control these locks...") { + input "locks", "capability.lock", multiple:true, required:false + } + section("Control these temperature sensors...") { + input "temperature_sensors", "capability.temperatureMeasurement", multiple:true, required:false + } + section("Control these batteries...") { + input "batteries", "capability.battery", multiple:true, required:false + } +} + +def installed() { + log.debug "Installed with settings: ${settings}" + + initialize() +} + +def updated() { + log.debug "Updated with settings: ${settings}" + + unsubscribe() + initialize() +} + +def initialize() { +} + +private device(it, type) { + it ? [id: it.id, label: it.label, type: type] : null +} + +//API Mapping +mappings { + path("/getalldevices") { + action: [ + GET: "getAllDevices" + ] + } + /* + path("/thermostat/setcool/:id/:temp") { + action: [ + GET: "setCoolTemp" + ] + } + path("/thermostat/setheat/:id/:temp") { + action: [ + GET: "setHeatTemp" + ] + } + path("/thermostat/setfanmode/:id/:mode") { + action: [ + GET: "setFanMode" + ] + } + path("/thermostat/setmode/:id/:mode") { + action: [ + GET: "setThermostatMode" + ] + } + path("/thermostat/:id") { + action: [ + GET: "getThermostatStatus" + ] + } + */ + path("/light/dim/:id/:dim") { + action: [ + GET: "setLevelStatus" + ] + } + path("/light/kelvin/:id/:kelvin") { + action: [ + GET: "setKelvin" + ] + } + path("/colorlight/:id/:hue/:sat") { + action: [ + GET: "setColor" + ] + } + path("/light/status/:id") { + action: [ + GET: "getLightStatus" + ] + } + path("/light/on/:id") { + action: [ + GET: "turnOnLight" + ] + } + path("/light/off/:id") { + action: [ + GET: "turnOffLight" + ] + } + path("/doorlocks/lock/:id") { + action: [ + GET: "lockDoorLock" + ] + } + path("/doorlocks/unlock/:id") { + action: [ + GET: "unlockDoorLock" + ] + } + path("/doorlocks/:id") { + action: [ + GET: "getDoorLockStatus" + ] + } + path("/contacts/:id") { + action: [ + GET: "getContactStatus" + ] + } + path("/smoke/:id") { + action: [ + GET: "getSmokeStatus" + ] + } + path("/shades/open/:id") { + action: [ + GET: "openShade" + ] + } + path("/shades/preset/:id") { + action: [ + GET: "presetShade" + ] + } + path("/shades/close/:id") { + action: [ + GET: "closeShade" + ] + } + path("/shades/:id") { + action: [ + GET: "getShadeStatus" + ] +} + path("/garage/open/:id") { + action: [ + GET: "openGarage" + ] + } + path("/garage/close/:id") { + action: [ + GET: "closeGarage" + ] + } + path("/garage/:id") { + action: [ + GET: "getGarageStatus" + ] + } + path("/watersensors/:id") { + action: [ + GET: "getWaterSensorStatus" + ] + } + path("/tempsensors/:id") { + action: [ + GET: "getTempSensorsStatus" + ] + } + path("/meters/:id") { + action: [ + GET: "getMeterStatus" + ] + } + path("/batteries/:id") { + action: [ + GET: "getBatteryStatus" + ] + } + path("/presences/:id") { + action: [ + GET: "getPresenceStatus" + ] + } + path("/motions/:id") { + action: [ + GET: "getMotionStatus" + ] + } + path("/outlets/:id") { + action: [ + GET: "getOutletStatus" + ] + } + path("/outlets/turnon/:id") { + action: [ + GET: "turnOnOutlet" + ] + } + path("/outlets/turnoff/:id") { + action: [ + GET: "turnOffOutlet" + ] + } + path("/switches/turnon/:id") { + action: [ + GET: "turnOnSwitch" + ] + } + path("/switches/turnoff/:id") { + action: [ + GET: "turnOffSwitch" + ] + } + path("/switches/:id") { + action: [ + GET: "getSwitchStatus" + ] + } +} + +//API Methods +def getAllDevices() { + def locks_list = locks.collect{device(it,"Lock")} + /*def thermo_list = thermostats.collect{device(it,"Thermostat")}*/ + def colors_list = colors.collect{device(it,"Color")} + def kelvin_list = kelvin.collect{device(it,"Kelvin")} + def contact_list = contact.collect{device(it,"Contact Sensor")} + def smokes_list = smoke_alarms.collect{device(it,"Smoke Alarm")} + def shades_list = shades.collect{device(it,"Window Shade")} + def garage_list = garage.collect{device(it,"Garage Door")} + def water_sensors_list = water_sensors.collect{device(it,"Water Sensor")} + def presences_list = presence_sensors.collect{device(it,"Presence")} + def motions_list = motions.collect{device(it,"Motion")} + def outlets_list = outlets.collect{device(it,"Outlet")} + def switches_list = switches.collect{device(it,"Switch")} + def switchlevels_list = switchlevels.collect{device(it,"Switch Level")} + def temp_list = temperature_sensors.collect{device(it,"Temperature")} + def meters_list = meters.collect{device(it,"Power Meters")} + def battery_list = batteries.collect{device(it,"Batteries")} + return outlets_list + kelvin_list + colors_list + switchlevels_list + smokes_list + contact_list + water_sensors_list + shades_list + garage_list + locks_list + presences_list + motions_list + switches_list + temp_list + meters_list + battery_list +} + +//thermostat +/* +def setCoolTemp() { + def device = thermostats.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + if(device.hasCommand("setCoolingSetpoint")) { + device.setCoolingSetpoint(params.temp.toInteger()); + return [result_action: "200"] + } + else { + httpError(510, "Not supported!") + } + } +} +def setHeatTemp() { + def device = thermostats.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + if(device.hasCommand("setHeatingSetpoint")) { + device.setHeatingSetpoint(params.temp.toInteger()); + return [result_action: "200"] + } + else { + httpError(510, "Not supported!") + } + } +} +def setFanMode() { + def device = thermostats.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + if(device.hasCommand("setThermostatFanMode")) { + device.setThermostatFanMode(params.mode); + return [result_action: "200"] + } + else { + httpError(510, "Not supported!") + } + } +} +def setThermostatMode() { + def device = thermostats.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + if(device.hasCommand("setThermostatMode")) { + device.setThermostatMode(params.mode); + return [result_action: "200"] + } + else { + httpError(510, "Not supported!") + } + } +} +def getThermostatStatus() { + def device = thermostats.find{ it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + return [ThermostatOperatingState: device.currentValue('thermostatOperatingState'), ThermostatSetpoint: device.currentValue('thermostatSetpoint'), + ThermostatFanMode: device.currentValue('thermostatFanMode'), ThermostatMode: device.currentValue('thermostatMode')] + } +} +*/ +//light +def turnOnLight() { + def device = switches.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + device.on(); + + return [Device_id: params.id, result_action: "200"] + } + } + +def turnOffLight() { + def device = switches.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + device.off(); + + return [Device_id: params.id, result_action: "200"] + } +} + +def getLightStatus() { + def device = switches.find{ it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + return [Status: device.currentValue('switch'), Dim: getLevelStatus(params.id), Color: getColorStatus(params.id), Kelvin: getKelvinStatus(params.id)] + } +} + +//color control +def setColor() { + def device = colors.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + + def map = [hue:params.hue.toInteger(), saturation:params.sat.toInteger()] + + device.setColor(map); + + return [Device_id: params.id, result_action: "200"] + } +} + +def getColorStatus(id) { + def device = colors.find { it.id == id } + if (!device) { + return [Color: "none"] + } else { + return [hue: device.currentValue('hue'), saturation: device.currentValue('saturation')] + } +} + +//kelvin control +def setKelvin() { + def device = kelvin.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + + device.setColorTemperature(params.kelvin.toInteger()); + + return [Device_id: params.id, result_action: "200"] + } +} + +def getKelvinStatus(id) { + def device = kelvin.find { it.id == id } + if (!device) { + return [kelvin: "none"] + } else { + return [kelvin: device.currentValue('colorTemperature')] + } +} + +//switch level +def getLevelStatus() { + def device = switchlevels.find { it.id == params.id } + if (!device) { + [Level: "No dimmer"] + } else { + return [Level: device.currentValue('level')] + } +} + +def getLevelStatus(id) { + def device = switchlevels.find { it.id == id } + if (!device) { + [Level: "No dimmer"] + } else { + return [Level: device.currentValue('level')] + } +} + + +def setLevelStatus() { + def device = switchlevels.find { it.id == params.id } + def level = params.dim + if (!device) { + httpError(404, "Device not found") + } else { + device.setLevel(level.toInteger()) + return [result_action: "200", Level: device.currentValue('level')] + } +} + + +//contact sensors +def getContactStatus() { + def device = contact.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + def args = getTempSensorsStatus(device.id) + return [Device_state: device.currentValue('contact')] + args + } +} + +//smoke detectors +def getSmokeStatus() { + def device = smoke_alarms.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + def bat = getBatteryStatus(device.id) + return [Device_state: device.currentValue('smoke')] + bat + } +} + +//garage +def getGarageStatus() { + def device = garage.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + return [Device_state: device.currentValue('door')] + } +} + +def openGarage() { + def device = garage.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + + device.open(); + + return [Device_id: params.id, result_action: "200"] + } + } + +def closeGarage() { + def device = garage.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + + device.close(); + + return [Device_id: params.id, result_action: "200"] + } + } +//shades +def getShadeStatus() { + def device = shades.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + return [Device_state: device.currentValue('windowShade')] + } +} + +def openShade() { + def device = shades.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + + device.open(); + + return [Device_id: params.id, result_action: "200"] + } + } + +def presetShade() { + def device = shades.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + + device.presetPosition(); + + return [Device_id: params.id, result_action: "200"] + } + } + +def closeShade() { + def device = shades.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + + device.close(); + + return [Device_id: params.id, result_action: "200"] + } + } + +//water sensor +def getWaterSensorStatus() { + def device = water_sensors.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + def bat = getBatteryStatus(device.id) + return [Device_state: device.currentValue('water')] + bat + } +} +//batteries +def getBatteryStatus() { + def device = batteries.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + return [Device_state: device.latestValue("battery")] + } +} + +def getBatteryStatus(id) { + def device = batteries.find { it.id == id } + if (!device) { + return [] + } else { + return [battery_state: device.latestValue("battery")] + } +} + +//LOCKS +def getDoorLockStatus() { + def device = locks.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + def bat = getBatteryStatus(device.id) + return [Device_state: device.currentValue('lock')] + bat + } +} + +def lockDoorLock() { + def device = locks.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + + device.lock(); + + return [Device_id: params.id, result_action: "200"] + } + } + +def unlockDoorLock() { + def device = locks.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + + device.unlock(); + + return [Device_id: params.id, result_action: "200"] + } + } +//PRESENCE +def getPresenceStatus() { + + def device = presence_sensors.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + def bat = getBatteryStatus(device.id) + return [Device_state: device.currentValue('presence')] + bat + } +} + +//MOTION +def getMotionStatus() { + + def device = motions.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + def args = getTempSensorsStatus(device.id) + return [Device_state: device.currentValue('motion')] + args + } +} + +//OUTLET +def getOutletStatus() { + + def device = outlets.find { it.id == params.id } + if (!device) { + device = switches.find { it.id == params.id } + if(!device) { + httpError(404, "Device not found") + } + } + def watt = getMeterStatus(device.id) + + return [Device_state: device.currentValue('switch')] + watt +} + +def getMeterStatus() { + + def device = meters.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + return [Device_id: device.id, Device_type: device.type, Current_watt: device.currentValue("power")] + } +} + +def getMeterStatus(id) { + + def device = meters.find { it.id == id } + if (!device) { + return [] + } else { + return [Current_watt: device.currentValue("power")] + } +} + + +def turnOnOutlet() { + def device = outlets.find { it.id == params.id } + if (!device) { + device = switches.find { it.id == params.id } + if(!device) { + httpError(404, "Device not found") + } + } + + device.on(); + + return [Device_id: params.id, result_action: "200"] +} + +def turnOffOutlet() { + def device = outlets.find { it.id == params.id } + if (!device) { + device = switches.find { it.id == params.id } + if(!device) { + httpError(404, "Device not found") + } + } + + device.off(); + + return [Device_id: params.id, result_action: "200"] +} + +//SWITCH +def getSwitchStatus() { + def device = switches.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + return [Device_state: device.currentValue('switch'), Dim: getLevelStatus(params.id)] + } +} + +def turnOnSwitch() { + def device = switches.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + + device.on(); + + return [Device_id: params.id, result_action: "200"] + } +} + +def turnOffSwitch() { + def device = switches.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + + device.off(); + + return [Device_id: params.id, result_action: "200"] + } +} + + +//TEMPERATURE +def getTempSensorsStatus() { + def device = temperature_sensors.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + def bat = getBatteryStatus(device.id) + def scale = [Scale: location.temperatureScale] + return [Device_state: device.currentValue('temperature')] + scale + bat + } +} + +def getTempSensorsStatus(id) { + def device = temperature_sensors.find { it.id == id } + if (!device) { + return [] + } else { + def bat = getBatteryStatus(device.id) + return [temperature: device.currentValue('temperature')] + bat + } + } \ No newline at end of file diff --git a/smartapps/michaelstruck/color-coordinator.src/color-coordinator.groovy b/smartapps/michaelstruck/color-coordinator.src/color-coordinator.groovy index f3d6ce2..dc5dfb7 100644 --- a/smartapps/michaelstruck/color-coordinator.src/color-coordinator.groovy +++ b/smartapps/michaelstruck/color-coordinator.src/color-coordinator.groovy @@ -1,10 +1,11 @@ /** * Color Coordinator - * Version 1.1.0 - 11/9/16 + * Version 1.1.1 - 11/9/16 * By Michael Struck * * 1.0.0 - Initial release * 1.1.0 - Fixed issue where master can be part of slaves. This causes a loop that impacts SmartThings. + * 1.1.1 - Fix NPE being thrown for slave/master inputs being empty. * * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except @@ -33,17 +34,17 @@ preferences { def mainPage() { dynamicPage(name: "mainPage", title: "", install: true, uninstall: false) { - def masterInList = slaves.id.find{it==master.id} + def masterInList = slaves?.id?.find{it==master?.id} if (masterInList) { section ("**WARNING**"){ paragraph "You have included the Master Light in the Slave Group. This will cause a loop in execution. Please remove this device from the Slave Group.", image: "https://raw.githubusercontent.com/MichaelStruck/SmartThingsPublic/master/img/caution.png" } } section("Master Light") { - input "master", "capability.colorControl", title: "Colored Light" + input "master", "capability.colorControl", title: "Colored Light", required: true } section("Lights that follow the master settings") { - input "slaves", "capability.colorControl", title: "Colored Lights", multiple: true, required: false, submitOnChange: true + input "slaves", "capability.colorControl", title: "Colored Lights", multiple: true, required: true, submitOnChange: true } section([mobileOnly:true], "Options") { input "randomYes", "bool",title: "When Master Turned On, Randomize Color", defaultValue: false @@ -81,40 +82,44 @@ def init() { } //----------------------------------- def onOffHandler(evt){ - if (!slaves.id.find{it==master.id}){ - if (master.currentValue("switch") == "on"){ - if (randomYes) getRandomColorMaster() - else slaves?.on() - } - else { - slaves?.off() - } + if (slaves && master) { + if (!slaves?.id.find{it==master?.id}){ + if (master?.currentValue("switch") == "on"){ + if (randomYes) getRandomColorMaster() + else slaves?.on() + } + else { + slaves?.off() + } + } } } def colorHandler(evt) { - if (!slaves.id.find{it==master.id} && master.currentValue("switch") == "on"){ - log.debug "Changing Slave units H,S,L" - def dimLevel = master.currentValue("level") - def hueLevel = master.currentValue("hue") - def saturationLevel = master.currentValue("saturation") - def newValue = [hue: hueLevel, saturation: saturationLevel, level: dimLevel as Integer] - slaves?.setColor(newValue) - try { - log.debug "Changing Slave color temp" - def tempLevel = master.currentValue("colorTemperature") - slaves?.setColorTemperature(tempLevel) - } - catch (e){ - log.debug "Color temp for master --" - } + if (slaves && master) { + if (!slaves?.id?.find{it==master?.id} && master?.currentValue("switch") == "on"){ + log.debug "Changing Slave units H,S,L" + def dimLevel = master?.currentValue("level") + def hueLevel = master?.currentValue("hue") + def saturationLevel = master.currentValue("saturation") + def newValue = [hue: hueLevel, saturation: saturationLevel, level: dimLevel as Integer] + slaves?.setColor(newValue) + try { + log.debug "Changing Slave color temp" + def tempLevel = master?.currentValue("colorTemperature") + slaves?.setColorTemperature(tempLevel) + } + catch (e){ + log.debug "Color temp for master --" + } + } } } def getRandomColorMaster(){ def hueLevel = Math.floor(Math.random() *1000) def saturationLevel = Math.floor(Math.random() * 100) - def dimLevel = master.currentValue("level") + def dimLevel = master?.currentValue("level") def newValue = [hue: hueLevel, saturation: saturationLevel, level: dimLevel as Integer] log.debug hueLevel log.debug saturationLevel @@ -123,12 +128,14 @@ def getRandomColorMaster(){ } def tempHandler(evt){ - if (!slaves.id.find{it==master.id} && master.currentValue("switch") == "on"){ - if (evt.value != "--") { - log.debug "Changing Slave color temp based on Master change" - def tempLevel = master.currentValue("colorTemperature") - slaves?.setColorTemperature(tempLevel) - } + if (slaves && master) { + if (!slaves?.id?.find{it==master?.id} && master?.currentValue("switch") == "on"){ + if (evt.value != "--") { + log.debug "Changing Slave color temp based on Master change" + def tempLevel = master.currentValue("colorTemperature") + slaves?.setColorTemperature(tempLevel) + } + } } } @@ -139,7 +146,7 @@ private def textAppName() { } private def textVersion() { - def text = "Version 1.1.0 (11/09/2016)" + def text = "Version 1.1.1 (12/13/2016)" } private def textCopyright() { @@ -166,4 +173,4 @@ private def textHelp() { "This application will allow you to control the settings of multiple colored lights with one control. " + "Simply choose a master control light, and then choose the lights that will follow the settings of the master, "+ "including on/off conditions, hue, saturation, level and color temperature. Also includes a random color feature." -} \ No newline at end of file +} diff --git a/smartapps/opent2t/opent2t-smartapp-test.src/opent2t-smartapp-test.groovy b/smartapps/opent2t/opent2t-smartapp-test.src/opent2t-smartapp-test.groovy new file mode 100644 index 0000000..91ddaef --- /dev/null +++ b/smartapps/opent2t/opent2t-smartapp-test.src/opent2t-smartapp-test.groovy @@ -0,0 +1,478 @@ +/** + * OpenT2T SmartApp Test + * + * Copyright 2016 OpenT2T + * + * 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: "OpenT2T SmartApp Test", + namespace: "opent2t", + author: "OpenT2T", + description: "Test app to test end to end SmartThings scenarios via OpenT2T", + category: "SmartThings Labs", + iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", + iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png", + iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png") + +/** --------------------+---------------+-----------------------+------------------------------------ + * Device Type | Attribute Name| Commands | Attribute Values + * --------------------+---------------+-----------------------+------------------------------------ + * switches | switch | on, off | on, off + * motionSensors | motion | | active, inactive + * contactSensors | contact | | open, closed + * presenceSensors | presence | | present, 'not present' + * temperatureSensors | temperature | | + * accelerationSensors | acceleration | | active, inactive + * waterSensors | water | | wet, dry + * lightSensors | illuminance | | + * humiditySensors | humidity | | + * locks | lock | lock, unlock | locked, unlocked + * garageDoors | door | open, close | unknown, closed, open, closing, opening + * cameras | image | take | + * thermostats | thermostat | setHeatingSetpoint, | temperature, heatingSetpoint, coolingSetpoint, + * | | setCoolingSetpoint, | thermostatSetpoint, thermostatMode, + * | | off, heat, cool, auto,| thermostatFanMode, thermostatOperatingState + * | | emergencyHeat, | + * | | setThermostatMode, | + * | | fanOn, fanAuto, | + * | | fanCirculate, | + * | | setThermostatFanMode | + * --------------------+---------------+-----------------------+------------------------------------ + */ + +//Device Inputs +preferences { + section("Allow OpenT2T to control these things...") { + 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 "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 + input "thermostats", "capability.thermostat", title: "Which Thermostat?", multiple: true, required: false + input "waterSensors", "capability.waterSensor", title: "Which Water Leak Sensors?", multiple: true, required: false + } +} + +def getInputs() { + def inputList = [] + 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: [ + PUT: "updateEndpointURL" + ] + } + path("/connectionId/:connId") { + action: [ + PUT: "updateConnectionId" + ] + } + path("/devices") { + action: [ + GET: "getDevices" + ] + } + path("/devices/:id") { + action: [ + GET: "getDevice" + ] + } + path("/update/:id") { + action: [ + PUT: "updateDevice" + ] + } + path("/subscription/:id") { + action: [ + POST: "registerDeviceChange", + DELETE: "unregisterDeviceChange" + ] + } +} + +def installed() { + log.debug "Installed with settings: ${settings}" + initialize() +} + +def updated() { + log.debug "Updated with settings: ${settings}" + unsubscribe() + registerSubscriptions() +} + +def initialize() { + state.connectionId = "" + state.endpointURL = "https://ifs.windows-int.com/v1/cb/81C7E77B-EABC-488A-B2BF-FEC42F0DABD2/notify" + registerSubscriptions() +} + +//Subscribe events for all devices +def registerSubscriptions() { + registerChangeHandler(inputs) +} + +//Subscribe to events from a list of devices +def registerChangeHandler(myList) { + myList.each { myDevice -> + def theAtts = myDevice.supportedAttributes + theAtts.each {att -> + subscribe(myDevice, att.name, eventHandler) + log.info "Registering ${myDevice.displayName}.${att.name}" + } + } +} + +//Endpoints function: Subscribe to events from a specific device +def registerDeviceChange() { + def myDevice = findDevice(params.id) + def theAtts = myDevice.supportedAttributes + try { + theAtts.each {att -> + subscribe(myDevice, att.name, eventHandler) + log.info "Registering ${myDevice.displayName}.${att.name}" + } + return ["succeed"] + } catch (e) { + httpError(500, "something went wrong: $e") + } +} + +//Endpoints function: Unsubscribe to events from a specific device +def unregisterDeviceChange() { + def myDevice = findDevice(params.id) + try { + unsubscribe(myDevice) + log.info "Unregistering ${myDevice.displayName}" + return ["succeed"] + } catch (e) { + httpError(500, "something went wrong: $e") + } +} + +//When events are triggered, send HTTP post to web socket servers +def eventHandler(evt) { + def evt_device_id = evt.deviceId + def evt_device_value = evt.value + 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: [ deviceInfo ] + ] + try { + log.trace "POST URI: ${params.uri}" + log.trace "Payload: ${params.body}" + httpPostJson(params) { resp -> + resp.headers.each { + log.debug "${it.name} : ${it.value}" + } + log.trace "response status code: ${resp.status}" + log.trace "response data: ${resp.data}" + } + } catch (e) { + log.debug "something went wrong: $e" + } +} + +//Endpoints function: update subcription endpoint url [state.endpoint] +void updateEndpointURL() { + state.endpointURL = params.url + log.info "Updated EndpointURL to ${state.endpointURL}" +} + +//Endpoints function: update global variable [state.connectionId] +void updateConnectionId() { + def connId = params.connId + state.connectionId = connId + log.info "Updated ConnectionID to ${state.connectionId}" +} + +//Endpoints function: return all device data in json format +def getDevices() { + def deviceData = [] + inputs?.each { + def deviceType = getDeviceType(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)] + } + } + + log.debug "getDevices, return: ${deviceData}" + return deviceData +} + +//Endpoints function: get device data +def getDevice() { + def it = findDevice(params.id) + def deviceType = getDeviceType(it) + def device + 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 +} + +//Endpoints function: update device data +void updateDevice() { + def device = findDevice(params.id) + request.JSON.each { + def command = it.key + def value = it.value + 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}) { + location.setMode(value) + } + }else if (command == "thermostatSetpoint"){ + switch(device.currentThermostatMode){ + case "cool": + log.info "Update: ${device.displayName}, [${command}, ${value}]" + device.setCoolingSetpoint(value) + break + case "heat": + case "emergency heat": + log.info "Update: ${device.displayName}, [${command}, ${value}]" + device.setHeatingSetpoint(value) + break + default: + httpError(501, "this mode: ${device.currentThermostatMode} does not allow changing thermostat setpoint.") + break + } + }else if (!device) { + log.error "updateDevice, Device not found" + httpError(404, "Device not found") + } else if (!device.hasCommand(command)) { + log.error "updateDevice, Device does not have the command" + httpError(404, "Device does not have such command") + } else { + if (command == "setColor") { + log.info "Update: ${device.displayName}, [${command}, ${value}]" + device."$command"(hex: value) + } else if(value.isNumber()) { + def intValue = value as Integer + log.info "Update: ${device.displayName}, [${command}, ${intValue}(int)]" + device."$command"(intValue) + } else if (value){ + log.info "Update: ${device.displayName}, [${command}, ${value}]" + device."$command"(value) + } else { + log.info "Update: ${device.displayName}, [${command}]" + device."$command"() + } + } + } + } +} + +/*** Private Functions ***/ + +//Return current location mode info +private getLocationModeInfo() { + return [mode: location.mode, supported: location.modes.name] +} + +//Map each device to a type given it's capabilities +private getDeviceType(device) { + def deviceType + def capabilities = device.capabilities + log.debug "capabilities: [${device}, ${capabilities}]" + log.debug "supported commands: [${device}, ${device.supportedCommands}]" + + //Loop through the device capability list to determine the device type. + capabilities.each {capability -> + switch(capability.name.toLowerCase()) + { + case "switch": + deviceType = "switch" + + //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": + deviceType = "contactSensor" + return deviceType + case "garageDoorControl": + deviceType = "garageDoor" + return deviceType + case "lock": + deviceType = "lock" + return deviceType + case "video camera": + deviceType = "camera" + return deviceType + case "motion sensor": + deviceType = "motionSensor" + return deviceType + case "presence sensor": + deviceType = "presenceSensor" + return deviceType + case "thermostat": + deviceType = "thermostat" + return deviceType + case "water sensor": + deviceType = "waterSensor" + return deviceType + default: + break + } + } + return deviceType +} + +//Return a specific device give the device ID. +private findDevice(deviceId) { + return inputs?.find { it.id == deviceId } +} + +//Return a list of device attributes +private deviceAttributeList(device) { + device.supportedAttributes.collectEntries { attribute-> + try { + [ (attribute.name): device.currentValue(attribute.name) ] + } catch(e) { + [ (attribute.name): null ] + } + } +} + +//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) { + log.debug "mapDeviceCommands: [${command}, ${value}]" + def resultCommand = command + def resultValue = value + switch (command) { + case "switch": + if (value == 1 || value == "1" || value == "on") { + resultCommand = "on" + resultValue = "" + } else if (value == 0 || value == "0" || value == "off") { + resultCommand = "off" + resultValue = "" + } + break + // light attributes + case "level": + resultCommand = "setLevel" + resultValue = value + break + case "hue": + resultCommand = "setHue" + resultValue = value + break + case "saturation": + resultCommand = "setSaturation" + resultValue = value + break + case "colorTemperature": + resultCommand = "setColorTemperature" + resultValue = value + break + case "color": + resultCommand = "setColor" + resultValue = value + // thermostat attributes + case "hvacMode": + resultCommand = "setThermostatMode" + resultValue = value + break + case "fanMode": + resultCommand = "setThermostatFanMode" + resultValue = value + break + case "awayMode": + resultCommand = "setAwayMode" + resultValue = value + break + case "coolingSetpoint": + resultCommand = "setCoolingSetpoint" + resultValue = value + break + case "heatingSetpoint": + resultCommand = "setHeatingSetpoint" + resultValue = value + break + case "thermostatSetpoint": + resultCommand = "thermostatSetpoint" + resultValue = value + break + // lock attributes + case "locked": + if (value == 1 || value == "1" || value == "lock") { + resultCommand = "lock" + resultValue = "" + } + else if (value == 0 || value == "0" || value == "unlock") { + resultCommand = "unlock" + resultValue = "" + } + break + default: + break + } + + return [resultCommand,resultValue] +} diff --git a/smartapps/osotech/plantlink-connector.src/plantlink-connector.groovy b/smartapps/osotech/plantlink-connector.src/plantlink-connector.groovy index 6a1423d..9421d23 100644 --- a/smartapps/osotech/plantlink-connector.src/plantlink-connector.groovy +++ b/smartapps/osotech/plantlink-connector.src/plantlink-connector.groovy @@ -57,7 +57,7 @@ def authPage(){ atomicState.accessToken = state.accessToken } - def redirectUrl = oauthInitUrl() + def redirectUrl = oauthInitUrl() def uninstallAllowed = false def oauthTokenProvided = false if(atomicState.authToken){ @@ -78,9 +78,9 @@ def authPage(){ } }else{ return dynamicPage(name: "auth", title: "Step 1 of 2 - Completed", nextPage:"deviceList", uninstall:uninstallAllowed) { - section(){ + section(){ paragraph "You are logged in to myplantlink.com, tap next to continue", image: iconUrl - href(url:redirectUrl, title:"Or", description:"tap to switch accounts") + href(url:redirectUrl, title:"Or", description:"tap to switch accounts") } } } @@ -137,36 +137,44 @@ def dock_sensor(device_serial, expected_plant_name) { contentType: "application/json", ] log.debug "Creating new plant on myplantlink.com - ${expected_plant_name}" - httpPost(docking_params) { docking_response -> - if (parse_api_response(docking_response, "Docking a link")) { - if (docking_response.data.plants.size() == 0) { - log.debug "creating plant for - ${expected_plant_name}" - plant_post_body_map["name"] = expected_plant_name - plant_post_body_map['links_key'] = [docking_response.data.key] - def plant_post_body_json_builder = new JsonBuilder(plant_post_body_map) - plant_post_params["body"] = plant_post_body_json_builder.toString() - httpPost(plant_post_params) { plant_post_response -> - if(parse_api_response(plant_post_response, 'creating plant')){ - def attached_map = atomicState.attached_sensors - attached_map[device_serial] = plant_post_response.data - atomicState.attached_sensors = attached_map + try { + httpPost(docking_params) { docking_response -> + if (parse_api_response(docking_response, "Docking a link")) { + if (docking_response.data.plants.size() == 0) { + log.debug "creating plant for - ${expected_plant_name}" + plant_post_body_map["name"] = expected_plant_name + plant_post_body_map['links_key'] = [docking_response.data.key] + def plant_post_body_json_builder = new JsonBuilder(plant_post_body_map) + plant_post_params["body"] = plant_post_body_json_builder.toString() + try { + httpPost(plant_post_params) { plant_post_response -> + if(parse_api_response(plant_post_response, 'creating plant')){ + def attached_map = atomicState.attached_sensors + attached_map[device_serial] = plant_post_response.data + atomicState.attached_sensors = attached_map + } + } + } catch (Exception f) { + log.debug "call failed $f" } + } else { + def plant = docking_response.data.plants[0] + def attached_map = atomicState.attached_sensors + attached_map[device_serial] = plant + atomicState.attached_sensors = attached_map + checkAndUpdatePlantIfNeeded(plant, expected_plant_name) } - } else { - def plant = docking_response.data.plants[0] - def attached_map = atomicState.attached_sensors - attached_map[device_serial] = plant - atomicState.attached_sensors = attached_map - checkAndUpdatePlantIfNeeded(plant, expected_plant_name) } } + } catch (Exception e) { + log.debug "call failed $e" } return true } def checkAndUpdatePlantIfNeeded(plant, expected_plant_name){ def plant_put_params = [ - uri : appSettings.https_plantLinkServer, + uri : appSettings.https_plantLinkServer, headers : ["Content-Type": "application/json", "Authorization": "Bearer ${atomicState.authToken}"], contentType : "application/json" ] @@ -174,12 +182,16 @@ def checkAndUpdatePlantIfNeeded(plant, expected_plant_name){ log.debug "updating plant for - ${expected_plant_name}" plant_put_params["path"] = "/api/v1/plants/${plant.key}" def plant_put_body_map = [ - name: expected_plant_name + name: expected_plant_name ] def plant_put_body_json_builder = new JsonBuilder(plant_put_body_map) plant_put_params["body"] = plant_put_body_json_builder.toString() - httpPut(plant_put_params) { plant_put_response -> - parse_api_response(plant_put_response, 'updating plant name') + try { + httpPut(plant_put_params) { plant_put_response -> + parse_api_response(plant_put_response, 'updating plant name') + } + } catch (Exception e) { + log.debug "call failed $e" } } } @@ -198,25 +210,29 @@ def moistureHandler(event){ contentType: "application/json", body: event.value ] - httpPost(measurement_post_params) { measurement_post_response -> - if (parse_api_response(measurement_post_response, 'creating moisture measurement') && - measurement_post_response.data.size() >0){ - def measurement = measurement_post_response.data[0] - def plant = measurement.plant - log.debug plant - checkAndUpdatePlantIfNeeded(plant, expected_plant_name) - plantlinksensors.each{ sensor_device -> - if (sensor_device.id == event.deviceId){ - sensor_device.setStatusIcon(plant.status) - if (plant.last_measurements && plant.last_measurements[0].moisture){ - sensor_device.setPlantFuelLevel(plant.last_measurements[0].moisture * 100 as int) - } - if (plant.last_measurements && plant.last_measurements[0].battery){ - sensor_device.setBatteryLevel(plant.last_measurements[0].battery * 100 as int) + try { + httpPost(measurement_post_params) { measurement_post_response -> + if (parse_api_response(measurement_post_response, 'creating moisture measurement') && + measurement_post_response.data.size() >0){ + def measurement = measurement_post_response.data[0] + def plant = measurement.plant + log.debug plant + checkAndUpdatePlantIfNeeded(plant, expected_plant_name) + plantlinksensors.each{ sensor_device -> + if (sensor_device.id == event.deviceId){ + sensor_device.setStatusIcon(plant.status) + if (plant.last_measurements && plant.last_measurements[0].moisture){ + sensor_device.setPlantFuelLevel(plant.last_measurements[0].moisture * 100 as int) + } + if (plant.last_measurements && plant.last_measurements[0].battery){ + sensor_device.setBatteryLevel(plant.last_measurements[0].battery * 100 as int) + } } } } } + } catch (Exception e) { + log.debug "call failed $e" } } } @@ -235,8 +251,12 @@ def batteryHandler(event){ contentType: "application/json", body: event.value ] - httpPost(measurement_post_params) { measurement_post_response -> - parse_api_response(measurement_post_response, 'creating battery measurement') + try { + httpPost(measurement_post_params) { measurement_post_response -> + parse_api_response(measurement_post_response, 'creating battery measurement') + } + } catch (Exception e) { + log.debug "call failed $e" } } } @@ -248,7 +268,7 @@ def getDeviceSerialFromEvent(event){ } def oauthInitUrl(){ - atomicState.oauthInitState = UUID.randomUUID().toString() + atomicState.oauthInitState = UUID.randomUUID().toString() def oauthParams = [ response_type: "code", client_id: appSettings.client_id, @@ -275,8 +295,12 @@ def swapToken(){ ] def jsonMap - httpPost(postParams) { resp -> - jsonMap = resp.data + try { + httpPost(postParams) { resp -> + jsonMap = resp.data + } + } catch (Exception e) { + log.debug "call failed $e" } atomicState.refreshToken = jsonMap.refresh_token @@ -287,33 +311,33 @@ def swapToken(){ -
-
PlantLink
-
connected to
-
SmartThings
-
+
+
PlantLink
+
connected to
+
SmartThings
+
-

Your PlantLink Account is now connected to SmartThings!

-

Click Done at the top right to finish setup.

-
+

Your PlantLink Account is now connected to SmartThings!

+

Click Done at the top right to finish setup.

+
""" diff --git a/smartapps/shabbatholidaymode/shabbat-and-holiday-modes.src/shabbat-and-holiday-modes.groovy b/smartapps/shabbatholidaymode/shabbat-and-holiday-modes.src/shabbat-and-holiday-modes.groovy index c6b5905..86b6b8d 100644 --- a/smartapps/shabbatholidaymode/shabbat-and-holiday-modes.src/shabbat-and-holiday-modes.groovy +++ b/smartapps/shabbatholidaymode/shabbat-and-holiday-modes.src/shabbat-and-holiday-modes.groovy @@ -30,7 +30,7 @@ preferences { input "havdalahOffset", "number", title: "Minutes After Sundown", required:true } section("Your ZipCode") { - input "zipcode", "number", title: "ZipCode", required:true + input "zipcode", "text", title: "ZipCode", required:true } section( "Notifications" ) { input "sendPushMessage", "enum", title: "Send a push notification?", metadata:[values:["Yes","No"]], required:false @@ -205,4 +205,4 @@ if ( sendPushMessage != "No" ) { log.debug( "sending text message" ) sendSms( phone, msg ) } -}//END def sendMessage(msg) \ No newline at end of file +}//END def sendMessage(msg) diff --git a/smartapps/smartthings/ecobee-connect.src/ecobee-connect.groovy b/smartapps/smartthings/ecobee-connect.src/ecobee-connect.groovy index 9b4c178..cc26358 100644 --- a/smartapps/smartthings/ecobee-connect.src/ecobee-connect.groovy +++ b/smartapps/smartthings/ecobee-connect.src/ecobee-connect.groovy @@ -20,6 +20,9 @@ * JLH - 02-15-2014 - Fuller use of ecobee API * 10-28-2015 DVCSMP-604 - accessory sensor, DVCSMP-1174, DVCSMP-1111 - not respond to routines */ + +include 'localization' + definition( name: "Ecobee (Connect)", namespace: "smartthings", @@ -78,7 +81,7 @@ def authPage() { return dynamicPage(name: "auth", title: "Select Your Thermostats", uninstall: true) { section("") { paragraph "Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings." - input(name: "thermostats", title:"", type: "enum", required:true, multiple:true, description: "Tap to choose", metadata:[values:stats]) + input(name: "thermostats", title:"Select Your Thermostats", type: "enum", required:true, multiple:true, description: "Tap to choose", metadata:[values:stats]) } def options = sensorsDiscovered() ?: [] @@ -86,7 +89,7 @@ def authPage() { if (numFound > 0) { section("") { paragraph "Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings." - input(name: "ecobeesensors", title:"Select Ecobee Sensors (${numFound} found)", type: "enum", required:false, description: "Tap to choose", multiple:true, options:options) + input(name: "ecobeesensors", title: "Select Ecobee Sensors ({{numFound}} found)", messageArgs: [numFound: numFound], type: "enum", required:false, description: "Tap to choose", multiple:true, options:options) } } } diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/ar-AE.properties b/smartapps/smartthings/ecobee-connect.src/i18n/ar-AE.properties new file mode 100644 index 0000000..ed44521 --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/ar-AE.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=قم بتوصيل ثرموستات Ecobee بـ SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=أنت متصل. +'''Click to enter Ecobee Credentials'''=النقر لإدخال بيانات اعتماد Ecobee +'''Login'''=تسجيل الدخول +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=انقر أدناه لتسجيل الدخول إلى خدمة ecobee والمصادقة على الوصول إلى SmartThings. تأكد من التمرير للأسفل على الصفحة ٢ والضغط على زر ”السماح“. +'''ecobee'''=ecobee +'''Select Your Thermostats'''=تحديد أجهزة الثرموستات +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=انقر أدناه لرؤية قائمة أجهزة ثرموستات ecobee المتوفرة في حساب ecobee، وحدد الأجهزة التي ترغب في توصيلها بـ SmartThings. +'''Tap to choose'''=النقر لاختيار +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=انقر أدناه لرؤية قائمة مستشعرات ecobee المتوفرة في حساب ecobee، وحدد الأجهزة التي ترغب في توصيلها بـ SmartThings. +'''Tap to choose'''=النقر لاختيار +'''Select Ecobee Sensors ({{numFound}} found)'''=تحديد مستشعرات Ecobee‏ ‎({{numFound}} found) +'''Your ecobee Account is now connected to SmartThings!'''=حساب ecobee متصل الآن بـ SmartThings! +'''Click 'Done' to finish setup.'''=انقر فوق ”تم“ لإنهاء الإعداد. +'''The connection could not be established!'''=يتعذر إنشاء الاتصال! +'''Click 'Done' to return to the menu.'''=انقر فوق ”تم“ للعودة إلى القائمة. +'''is connected to SmartThings'''={{deviceName}} متصل بـ SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=تم قطع اتصال {{deviceName}} بـ SmartThings، لأن بيانات اعتماد الوصول قد تغيرت أو فُقدت. يُرجى الانتقال إلى التطبيق الذكي Ecobee (Connect)‎ وإعادة إدخال بيانات اعتماد تسجيل الدخول إلى حسابك. +'''Your Ecobee thermostat '''=ثرموستات Ecobee diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/bg-BG.properties b/smartapps/smartthings/ecobee-connect.src/i18n/bg-BG.properties new file mode 100644 index 0000000..5415a62 --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/bg-BG.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Свържете термостата Ecobee към SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=Свързани сте. +'''Click to enter Ecobee Credentials'''=Щракнете, за да въведете идентификационни данни за Ecobee +'''Login'''=Вход +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Докоснете по-долу, за да влезете в услугата ecobee и да упълномощите достъпа на SmartThings. Превъртете надолу в страница 2 и натиснете бутона Allow (Позволяване). +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Избор на термостати +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Докоснете по-долу, за да видите списък с термостатите ecobee във вашия ecobee акаунт, и изберете онези, които искате да свържете към SmartThings. +'''Tap to choose'''=Докосване за избор +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Докоснете по-долу, за да видите списък със сензорите ecobee във вашия ecobee акаунт, и изберете онези, които искате да свържете към SmartThings. +'''Tap to choose'''=Докосване за избор +'''Select Ecobee Sensors ({{numFound}} found)'''=Избор на сензори Ecobee ({{numFound}} с намерени) +'''Your ecobee Account is now connected to SmartThings!'''=Вашият ecobee акаунт вече е свързан към SmartThings! +'''Click 'Done' to finish setup.'''=Щракнете върху Done (Готово), за да завършите настройката. +'''The connection could not be established!'''=Връзката не може да се осъществи! +'''Click 'Done' to return to the menu.'''=Щракнете върху Done (Готово), за да се върнете към менюто. +'''is connected to SmartThings'''=е свързан към SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=е прекъснат от SmartThings, тъй като идентификационните данни за достъп са променени или изгубени. Отидете в Ecobee (Connect) SmartApp и въведете отново идентификационните си данни за влизане в акаунта. +'''Your Ecobee thermostat '''=Вашият термостат Ecobee diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/cs-CZ.properties b/smartapps/smartthings/ecobee-connect.src/i18n/cs-CZ.properties new file mode 100644 index 0000000..ad84594 --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/cs-CZ.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Připojte termostat Ecobee k systému SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=Jste připojeni. +'''Click to enter Ecobee Credentials'''=Klepněte a zadejte přihlašovací údaje Ecobee +'''Login'''=Přihlásit +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Klepnutím na následující tlačítko se přihlásíte ke službě ecobee a autorizujete přístup pro systém SmartThings. Posuňte se dolů na stránku 2 a stiskněte tlačítko „Allow“ (Povolit). +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Vyberte termostaty +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Klepnutím na následující tlačítko zobrazte seznam termostatů ecobee dostupných na vašem účtu ecobee a vyberte ty, které chcete připojit k systému SmartThings. +'''Tap to choose'''=Klepnutím zvolte +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Klepnutím na následující tlačítko zobrazte seznam senzorů ecobee dostupných na vašem účtu ecobee a vyberte ty, které chcete připojit k systému SmartThings. +'''Tap to choose'''=Klepnutím zvolte +'''Select Ecobee Sensors ({{numFound}} found)'''=Vyberte senzory Ecobee (nalezeno {{numFound}}) +'''Your ecobee Account is now connected to SmartThings!'''=Účet ecobee je nyní připojen k systému SmartThings! +'''Click 'Done' to finish setup.'''=Dokončete nastavení klepnutím na tlačítko „Done“ (Hotovo). +'''The connection could not be established!'''=Připojení nelze navázat! +'''Click 'Done' to return to the menu.'''=Klepnutím na tlačítko „Done“ (Hotovo) se vrátíte do menu. +'''is connected to SmartThings'''=je připojen ke SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=byl odpojen od systému SmartThings, protože přístupové přihlašovací údaje byly změněny nebo ztraceny. Přejděte do Ecobee (Connect) SmartApp a znovu zadejte své přihlašovací údaje k účtu. +'''Your Ecobee thermostat '''=Termostat Ecobee diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/da-DK.properties b/smartapps/smartthings/ecobee-connect.src/i18n/da-DK.properties new file mode 100644 index 0000000..3ff6127 --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/da-DK.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Forbind din Ecobee-termostat med SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=Du er nu forbundet. +'''Click to enter Ecobee Credentials'''=Klik for at indtaste Ecobee-legitimationsoplysninger +'''Login'''=Log ind +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Tryk nedenfor for at logge ind på din ecobee-tjeneste og godkende SmartThings-adgang. Sørg for at rulle ned på side 2 og trykke på knappen “Allow” (Tillad). +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Vælg dine termostater +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Tryk herunder for at se listen over ecobee-termostater, der er tilgængelige på din ecobee-konto, og vælg dem, du vil forbinde med SmartThings. +'''Tap to choose'''=Tryk for at vælge +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Tryk herunder for at se listen over ecobee-sensorer, der er tilgængelige på din ecobee-konto, og vælg dem, du vil forbinde med SmartThings. +'''Tap to choose'''=Tryk for at vælge +'''Select Ecobee Sensors ({{numFound}} found)'''=Vælg Ecobee-sensorer ({{numFound}} fundet) +'''Your ecobee Account is now connected to SmartThings!'''=Din ecobee-konto er nu forbundet med SmartThings! +'''Click 'Done' to finish setup.'''=Klik på “Done” (Udført) for at afslutte konfigurationen. +'''The connection could not be established!'''=Der kunne ikke oprettes forbindelse! +'''Click 'Done' to return to the menu.'''=Klik på “Done” (Udført) for at vende tilbage til menuen. +'''is connected to SmartThings'''=er forbundet med SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=er koblet fra SmartThings, fordi adgangslegitimationsoplysningerne er ændret eller gået tabt. Gå til Ecobee (Connect (Forbind)) SmartApp, og indtast dine kontologinoplysninger igen. +'''Your Ecobee thermostat '''=Din Ecobee-termostat diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/de-DE.properties b/smartapps/smartthings/ecobee-connect.src/i18n/de-DE.properties new file mode 100644 index 0000000..1c4318d --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/de-DE.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Verbinden Sie Ihr Ecobee-Thermostat mit SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=Sie sind verbunden. +'''Click to enter Ecobee Credentials'''=Hier klicken, um die ecobee-Zugangsdaten einzugeben. +'''Login'''=Anmeldung +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Tippen Sie unten, um sich am ecobee-Dienst anzumelden und den SmartThings-Zugriff zu autorisieren. Stellen Sie sicher, dass Sie bis auf Seite 2 herunterscrollen und auf die Schaltfläche „Allow“ (Zulassen) tippen. +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Ihre Thermostate auswählen +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Tippen Sie unten, um eine Liste der ecobee-Thermostate anzuzeigen, die in Ihrem ecobee-Konto verfügbar sind, und wählen Sie diejenigen aus, mit denen Sie eine Verbindung zu SmartThings herstellen möchten. +'''Tap to choose'''=Zur Auswahl tippen +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Tippen Sie unten, um eine Liste der ecobee-Sensoren anzuzeigen, die in Ihrem ecobee-Konto verfügbar sind, und wählen Sie diejenigen aus, mit denen Sie eine Verbindung zu SmartThings herstellen möchten. +'''Tap to choose'''=Zur Auswahl tippen +'''Select Ecobee Sensors ({{numFound}} found)'''=ecobee-Sensoren auswählen ({{numFound}} gefunden) +'''Your ecobee Account is now connected to SmartThings!'''=Ihr ecobee-Konto ist jetzt mit SmartThings verbunden! +'''Click 'Done' to finish setup.'''=Klicken Sie auf „Done“ (OK), um die Einrichtung abzuschließen. +'''The connection could not be established!'''=Es konnte keine Verbindung hergestellt werden! +'''Click 'Done' to return to the menu.'''=Klicken Sie auf „Done“ (OK), um zum Menü zurückzukehren. +'''is connected to SmartThings'''=ist mit SmartThings verbunden +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=ist von SmartThings getrennt, da die Zugangsdaten für den Zugriff geändert wurden oder verloren gingen. Wechseln Sie zur ecobee (Connect)-SmartApp und geben Sie Ihre Kontozugangsdaten erneut ein. +'''Your Ecobee thermostat '''=Ihr ecobee-Thermostat diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/el-GR.properties b/smartapps/smartthings/ecobee-connect.src/i18n/el-GR.properties new file mode 100644 index 0000000..3d3268b --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/el-GR.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Συνδέστε το θερμοστάτη Ecobee στο SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=Έχετε συνδεθεί. +'''Click to enter Ecobee Credentials'''=Κάντε κλικ για να καταχωρήσετε διαπιστευτήρια Ecobee +'''Login'''=Σύνδεση +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Πατήστε παρακάτω για να συνδεθείτε στην υπηρεσία ecobee και να δώσετε εξουσιοδότηση πρόσβασης για το SmartThings. Κάνετε κύλιση προς τα κάτω στη σελίδα 2 και πατήστε το κουμπί "Επιτρ.". +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Επιλέξτε τους θερμοστάτες σας +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Πατήστε παρακάτω για να δείτε τη λίστα με τους θερμοστάτες ecobee που είναι διαθέσιμοι στο λογαριασμό ecobee και να επιλέξετε αυτούς που θέλετε να συνδέσετε στο SmartThings. +'''Tap to choose'''=Πατήστε για να επιλέξετε +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Πατήστε παρακάτω για να δείτε τη λίστα με τους αισθητήρες ecobee που είναι διαθέσιμοι στο λογαριασμό ecobee και να επιλέξετε αυτούς που θέλετε να συνδέσετε στο SmartThings. +'''Tap to choose'''=Πατήστε για να επιλέξετε +'''Select Ecobee Sensors ({{numFound}} found)'''=Επιλογή αισθητήρων Ecobee (βρέθηκαν {{numFound}}) +'''Your ecobee Account is now connected to SmartThings!'''=Ο λογαριασμός σας στο ecobee έχει τώρα συνδεθεί στο SmartThings! +'''Click 'Done' to finish setup.'''=Πατήστε "Done" (Τέλος) για να ολοκληρωθεί η ρύθμιση. +'''The connection could not be established!'''=Δεν ήταν δυνατή η δημιουργία σύνδεσης! +'''Click 'Done' to return to the menu.'''=Κάντε κλικ στο "Done" (Τέλος) για να επιστρέψετε στο μενού. +'''is connected to SmartThings'''=συνδέθηκε στο SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=αποσυνδέθηκε από το SmartThings, επειδή τα διαπιστευτήρια πρόσβασης άλλαξαν ή έχουν χαθεί. Μεταβείτε στην εφαρμογή Ecobee (Connect) SmartApp και καταχωρήστε ξανά τα διαπιστευτήρια σύνδεσης για το λογαριασμό σας. +'''Your Ecobee thermostat '''=Θερμοστάτης Ecobee diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/en-GB.properties b/smartapps/smartthings/ecobee-connect.src/i18n/en-GB.properties new file mode 100644 index 0000000..578e383 --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/en-GB.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Connect your Ecobee thermostat to SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=You are connected. +'''Click to enter Ecobee Credentials'''=Click to enter Ecobee Credentials +'''Login'''=Login +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Tap below to log in to the ecobee service and authorise SmartThings access. Be sure to scroll down on page 2 and press the ’Allow’ button. +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Select Your Thermostats +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings. +'''Tap to choose'''=Tap to choose +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings. +'''Tap to choose'''=Tap to choose +'''Select Ecobee Sensors ({{numFound}} found)'''=Select Ecobee Sensors ({{numFound}} found) +'''Your ecobee Account is now connected to SmartThings!'''=Your ecobee Account is now connected to SmartThings! +'''Click 'Done' to finish setup.'''=Click ’Done’ to finish setup. +'''The connection could not be established!'''=The connection could not be established! +'''Click 'Done' to return to the menu.'''=Click ’Done’ to return to the menu. +'''is connected to SmartThings'''=is connected to SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials. +'''Your Ecobee thermostat '''=Your Ecobee thermostat diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/es-ES.properties b/smartapps/smartthings/ecobee-connect.src/i18n/es-ES.properties new file mode 100644 index 0000000..e8ff069 --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/es-ES.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Conecte su termostato Ecobee a SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=Está conectado. +'''Click to enter Ecobee Credentials'''=Haga clic para introducir las credenciales de Ecobee +'''Login'''=Inicio de sesión +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Pulse a continuación para iniciar sesión en el servicio de ecobee y autorizar el acceso a SmartThings. Asegúrese de desplazarse hacia abajo a la página 2 y pulsar el botón “Allow” (Permitir). +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Seleccionar los termostatos +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Pulse a continuación para ver la lista de termostatos ecobee disponibles en su cuenta de ecobee y seleccione los que quiera conectar a SmartThings. +'''Tap to choose'''=Pulsar para seleccionar +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Pulse a continuación para ver la lista de sensores ecobee disponibles en su cuenta de ecobee y seleccione los que quiera conectar a SmartThings. +'''Tap to choose'''=Pulsar para seleccionar +'''Select Ecobee Sensors ({{numFound}} found)'''=Seleccionar sensores de Ecobee ({{numFound}} encontrados) +'''Your ecobee Account is now connected to SmartThings!'''=¡Su cuenta de ecobee ya está conectada a SmartThings! +'''Click 'Done' to finish setup.'''=Haga clic en “Done” (Hecho) para finalizar la configuración. +'''The connection could not be established!'''=¡No se ha podido establecer la conexión! +'''Click 'Done' to return to the menu.'''=Haga clic en “Done” (Hecho) para volver al menú. +'''is connected to SmartThings'''=está conectado a SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=está desconectado de SmartThings porque se han cambiado o perdido las credenciales de acceso. Vaya a la aplicación inteligente de Ecobee (Conectar) y vuelva a introducir las credenciales de inicio de sesión de su cuenta. +'''Your Ecobee thermostat '''=Su termostato Ecobee diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/es-US.properties b/smartapps/smartthings/ecobee-connect.src/i18n/es-US.properties new file mode 100644 index 0000000..761224e --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/es-US.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Conecte el termostato Ecobee a SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=Está conectado. +'''Click to enter Ecobee Credentials'''=Haga clic para introducir las credenciales de Ecobee +'''Login'''=Inicio de sesión +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Pulse a continuación para iniciar sesión en el servicio de ecobee y otorgar acceso a SmartThings. Asegúrese de desplazarse hacia abajo en la página 2 y de presionar el botón 'Allow' ('Permitir'). +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Seleccionar Your Thermostats (Sus termostatos) +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Pulse a continuación para ver la lista de termostatos ecobee disponibles en su cuenta de ecobee y seleccione los que desea conectar a SmartThings. +'''Tap to choose'''=Pulsar para elegir +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Pulse a continuación para ver la lista de sensores ecobee disponibles en su cuenta de ecobee y seleccione los que desea conectar a SmartThings. +'''Tap to choose'''=Pulsar para elegir +'''Select Ecobee Sensors ({{numFound}} found)'''=Seleccionar sensores Ecobee (hay {{numFound}}) +'''Your ecobee Account is now connected to SmartThings!'''=¡Su cuenta de ecobee ahora está conectada a SmartThings! +'''Click 'Done' to finish setup.'''=Haga clic en 'Done' ('Listo') para finalizar la configuración. +'''The connection could not be established!'''=¡No fue posible establecer la conexión! +'''Click 'Done' to return to the menu.'''=Haga clic en 'Done' ('Listo') para volver al menú. +'''is connected to SmartThings'''=está conectado a SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=no está conectado a SmartThings debido a que la credencial de acceso se cambió o se perdió. Vaya a la SmartApp de Ecobee (Connect) y vuelva a introducir las credenciales de inicio de sesión de su cuenta. +'''Your Ecobee thermostat '''=Su termostato Ecobee diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/et-EE.properties b/smartapps/smartthings/ecobee-connect.src/i18n/et-EE.properties new file mode 100644 index 0000000..2244b2a --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/et-EE.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Ühendage oma termostaat Ecobee teenusega SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=Ühendus on loodud. +'''Click to enter Ecobee Credentials'''=Klõpsake, et sisestada teenuse Ecobee volitused +'''Login'''=Sisselogimine +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Toksake all, et logida sisse teenusesse ecobee ja autoriseerida teenuse SmartThings juurdepääs. Kerige kindlasti alla lehele 2 ja vajutage nuppu Luba. +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Valige oma termostaadid +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Toksake all, et näha oma ecobee kontole registreeritud ecobee termostaate ja valige need, mida soovite ühendada teenusega SmartThings. +'''Tap to choose'''=Toksake, et valida +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Toksake all, et näha oma ecobee kontole registreeritud ecobee andureid ja valige need, mida soovite ühendada teenusega SmartThings. +'''Tap to choose'''=Toksake, et valida +'''Select Ecobee Sensors ({{numFound}} found)'''=Valige Ecobee andurid (leiti {{numFound}}) +'''Your ecobee Account is now connected to SmartThings!'''=Teie ecobee konto on nüüd ühendatud teenusega SmartThings! +'''Click 'Done' to finish setup.'''=Klõpsake valikut Valmis, et seadistamine lõpule viia. +'''The connection could not be established!'''=Ühenduse loomine nurjus! +'''Click 'Done' to return to the menu.'''=Klõpsake valikut Valmis, et naasta menüüsse. +'''is connected to SmartThings'''=on ühendatud teenusega SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=on teenusest SmartThings lahti ühendatud, kuna juurdepääsu volitus muutus või kadus. Avage rakendus Ecobee (Connect) SmartApp ja sisestage uuesti oma konto sisselogimisandmed. +'''Your Ecobee thermostat '''=Teie Ecobee termostaat diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/fi-FI.properties b/smartapps/smartthings/ecobee-connect.src/i18n/fi-FI.properties new file mode 100644 index 0000000..5f38b39 --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/fi-FI.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Yhdistä Ecobee-termostaattisi SmartThingsiin. +'''ecobee'''=ecobee +'''You are connected.'''=Yhteys muodostettu. +'''Click to enter Ecobee Credentials'''=Napsauta ja anna Ecobee-tunnistetiedot +'''Login'''=Kirjautuminen +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Kirjaudu ecobee-palveluun ja myönnä SmartThingsille käyttöoikeudet napauttamalla alla. Vieritä alas sivulle 2 ja paina Allow (Salli) -painiketta. +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Valitse termostaatit +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Napauttamalla alla voit tuoda ecobee-tililläsi käytettävissä olevien ecobee-termostaattien luettelon näyttöön ja valita SmartThingsiin yhdistettävät laitteet. +'''Tap to choose'''=Valitse napauttamalla +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Napauttamalla alla voit tuoda ecobee-tililläsi käytettävissä olevien ecobee-tunnistimien luettelon näyttöön ja valita SmartThingsiin yhdistettävät laitteet. +'''Tap to choose'''=Valitse napauttamalla +'''Select Ecobee Sensors ({{numFound}} found)'''=Valitse Ecobee-tunnistimet ({{numFound}} löydetty) +'''Your ecobee Account is now connected to SmartThings!'''=ecobee-tilisi on nyt yhdistetty SmartThingsiin! +'''Click 'Done' to finish setup.'''=Viimeistele asennus napsauttamalla Done (Valmis). +'''The connection could not be established!'''=Yhteyden muodostaminen epäonnistui! +'''Click 'Done' to return to the menu.'''=Palaa valikkoon napsauttamalla Done (Valmis). +'''is connected to SmartThings'''=on yhdistetty SmartThingsiin +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=ei enää ole yhteydessä SmartThingsiin, sillä käyttötunnukset ovat muuttuneet tai kadonneet. Siirry Ecobee (Connect) SmartAppiin ja anna tilisi kirjautumistiedot uudelleen. +'''Your Ecobee thermostat '''=Ecobee-termostaattisi diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/fr-CA.properties b/smartapps/smartthings/ecobee-connect.src/i18n/fr-CA.properties new file mode 100644 index 0000000..e1b7486 --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/fr-CA.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Connectez votre thermostat Ecobee à SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=Vous êtes connecté. +'''Click to enter Ecobee Credentials'''=Cliquez pour saisir les informations d'identification Ecobee +'''Login'''=Connexion +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Appuyez ci-dessous pour vous connecter au service ecobee et autoriser l'accès pour SmartThings. Faites défiler l'écran jusqu'en bas de la page 2 et appuyez sur le bouton Allow (Autoriser). +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Sélection de vos thermostats +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Appuyez ci-dessous pour afficher la liste des thermostats ecobee disponibles dans votre compte ecobee et sélectionner ceux que vous souhaitez connecter à SmartThings. +'''Tap to choose'''=Appuyez pour sélectionner +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Appuyez ci-dessous pour afficher la liste des capteurs ecobee disponibles dans votre compte ecobee et sélectionner ceux que vous souhaitez connecter à SmartThings. +'''Tap to choose'''=Appuyez pour sélectionner +'''Select Ecobee Sensors ({{numFound}} found)'''=Sélection des capteurs Ecobee ({{numFound}} trouvé(s)) +'''Your ecobee Account is now connected to SmartThings!'''=Votre compte ecobee est maintenant connecté à SmartThings ! +'''Click 'Done' to finish setup.'''=Cliquez sur Done (Terminé) pour terminer la configuration. +'''The connection could not be established!'''=La connexion n'a pas pu être établie ! +'''Click 'Done' to return to the menu.'''=Cliquez sur Done (Terminé) pour revenir au menu. +'''is connected to SmartThings'''=est connecté à SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=est déconnecté de SmartThings, car les identifiants d'accès ont été modifiés ou perdus. Accédez à la SmartApp Ecobee (Connect) et saisissez à nouveau les informations de connexion à votre compte. +'''Your Ecobee thermostat '''=Votre thermostat Ecobee diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/fr-FR.properties b/smartapps/smartthings/ecobee-connect.src/i18n/fr-FR.properties new file mode 100644 index 0000000..e1b7486 --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/fr-FR.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Connectez votre thermostat Ecobee à SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=Vous êtes connecté. +'''Click to enter Ecobee Credentials'''=Cliquez pour saisir les informations d'identification Ecobee +'''Login'''=Connexion +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Appuyez ci-dessous pour vous connecter au service ecobee et autoriser l'accès pour SmartThings. Faites défiler l'écran jusqu'en bas de la page 2 et appuyez sur le bouton Allow (Autoriser). +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Sélection de vos thermostats +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Appuyez ci-dessous pour afficher la liste des thermostats ecobee disponibles dans votre compte ecobee et sélectionner ceux que vous souhaitez connecter à SmartThings. +'''Tap to choose'''=Appuyez pour sélectionner +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Appuyez ci-dessous pour afficher la liste des capteurs ecobee disponibles dans votre compte ecobee et sélectionner ceux que vous souhaitez connecter à SmartThings. +'''Tap to choose'''=Appuyez pour sélectionner +'''Select Ecobee Sensors ({{numFound}} found)'''=Sélection des capteurs Ecobee ({{numFound}} trouvé(s)) +'''Your ecobee Account is now connected to SmartThings!'''=Votre compte ecobee est maintenant connecté à SmartThings ! +'''Click 'Done' to finish setup.'''=Cliquez sur Done (Terminé) pour terminer la configuration. +'''The connection could not be established!'''=La connexion n'a pas pu être établie ! +'''Click 'Done' to return to the menu.'''=Cliquez sur Done (Terminé) pour revenir au menu. +'''is connected to SmartThings'''=est connecté à SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=est déconnecté de SmartThings, car les identifiants d'accès ont été modifiés ou perdus. Accédez à la SmartApp Ecobee (Connect) et saisissez à nouveau les informations de connexion à votre compte. +'''Your Ecobee thermostat '''=Votre thermostat Ecobee diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/hr-HR.properties b/smartapps/smartthings/ecobee-connect.src/i18n/hr-HR.properties new file mode 100644 index 0000000..68794da --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/hr-HR.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Povežite termostat Ecobee s uslugom SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=Povezani ste. +'''Click to enter Ecobee Credentials'''=Kliknite za unos podataka za prijavu za Ecobee +'''Login'''=Prijava +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Dodirnite u nastavku da biste se prijavili u uslugu ecobee i odobrili pristup za SmartThings. Na 2. se stranici pomaknite prema dolje i pritisnite gumb „Allow” (Dopusti). +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Odaberite termostate +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Dodirnite u nastavku da biste vidjeli popis termostata ecobee dostupnih na vašem računu za ecobee i odaberite one koje želite povezati s uslugom SmartThings. +'''Tap to choose'''=Dodirnite za odabir +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Dodirnite u nastavku da biste vidjeli popis senzora ecobee dostupnih na vašem računu za ecobee i odaberite one koje želite povezati s uslugom SmartThings. +'''Tap to choose'''=Dodirnite za odabir +'''Select Ecobee Sensors ({{numFound}} found)'''=Odaberite senzore Ecobee (pronađeno: {{numFound}}) +'''Your ecobee Account is now connected to SmartThings!'''=Račun za ecobee sada je povezan s uslugom SmartThings! +'''Click 'Done' to finish setup.'''=Kliknite „Done” (Gotovo) da biste dovršili postavljanje. +'''The connection could not be established!'''=Veza se nije uspostavila! +'''Click 'Done' to return to the menu.'''=Kliknite „Done” (Gotovo) za vraćanje na izbornik. +'''is connected to SmartThings'''=povezan je s uslugom SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=nije povezan s uslugom SmartThings jer su se pristupni podaci promijenili ili izgubili. Idite na Ecobee (Connect) SmartApp i ponovno unesite podatke za prijavu na račun. +'''Your Ecobee thermostat '''=Termostat Ecobee diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/hu-HU.properties b/smartapps/smartthings/ecobee-connect.src/i18n/hu-HU.properties new file mode 100644 index 0000000..1ed4b71 --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/hu-HU.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Ecobee termosztátot csatlakoztathat a SmartThings rendszerhez. +'''ecobee'''=ecobee +'''You are connected.'''=Kapcsolódott. +'''Click to enter Ecobee Credentials'''=Kattintson az Ecobee-hitelesítőadatok megadásához +'''Login'''=Bejelentkezés +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Az alábbi hivatkozás megérintésével bejelentkezhet az ecobee szolgáltatásba, és engedélyezheti a SmartThings-hozzáférést. Görgessen le a 2. oldalon, és nyomja meg az „Allow” (Engedélyezés) gombot. +'''ecobee'''=ecobee +'''Select Your Thermostats'''=A termosztátok kiválasztása +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Az alábbi hivatkozás megérintésével megjelenítheti az ecobee-fiókjában rendelkezésre álló ecobee termosztátok listáját, és kiválaszthatja azokat, amelyeket csatlakoztatni szeretne a SmartThings rendszerhez. +'''Tap to choose'''=Érintse meg a kiválasztáshoz +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Az alábbi hivatkozás megérintésével megjelenítheti az ecobee-fiókjában rendelkezésre álló ecobee érzékelők listáját, és kiválaszthatja azokat, amelyeket csatlakoztatni szeretne a SmartThings rendszerhez. +'''Tap to choose'''=Érintse meg a kiválasztáshoz +'''Select Ecobee Sensors ({{numFound}} found)'''=Ecobee érzékelők kiválasztása ({{numFound}} találat) +'''Your ecobee Account is now connected to SmartThings!'''=Csatlakoztatta ecobee-fiókját a SmartThings rendszerhez! +'''Click 'Done' to finish setup.'''=A telepítés befejezéséhez kattintson a „Done” (Kész) gombra. +'''The connection could not be established!'''=Nem sikerült kapcsolatot létesíteni! +'''Click 'Done' to return to the menu.'''=A menühöz való visszatéréshez kattintson a „Done” (Kész) gombra. +'''is connected to SmartThings'''=kapcsolódott a SmartThings rendszerhez +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=le lett választva a SmartThings rendszerről, mert megváltoztak vagy elvesztek a hozzáférési hitelesítő adatok. Adja meg újra a fiókja bejelentkezési hitelesítő adatait a Ecobee (Connect) SmartApp segítségével. +'''Your Ecobee thermostat '''=Az Ön Ecobee termosztátja diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/it-IT.properties b/smartapps/smartthings/ecobee-connect.src/i18n/it-IT.properties new file mode 100644 index 0000000..1265151 --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/it-IT.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Connettete il termostato Ecobee a SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=Connessione effettuata. +'''Click to enter Ecobee Credentials'''=Fate clic per inserire le credenziali Ecobee +'''Login'''=Accesso +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Toccate di seguito per accedere al servizio ecobee e autorizzare l'accesso a SmartThings. Scorrete fino in fondo alla pagina 2 e premete il pulsante “Allow” (Consenti). +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Selezionate i termostati +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Toccate di seguito per visualizzare l'elenco dei termostati ecobee disponibili nell'account ecobee e selezionate quelli che volete connettere a SmartThings. +'''Tap to choose'''=Toccate per scegliere +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Toccate di seguito per visualizzare l'elenco dei sensori ecobee disponibili nell'account ecobee e selezionate quelli che volete connettere a SmartThings. +'''Tap to choose'''=Toccate per scegliere +'''Select Ecobee Sensors ({{numFound}} found)'''=Selezionate i sensori Ecobee ({{numFound}} trovati) +'''Your ecobee Account is now connected to SmartThings!'''=L'account ecobee è ora connesso a SmartThings. +'''Click 'Done' to finish setup.'''=Fate clic su “Done” (Fatto) per terminare la configurazione. +'''The connection could not be established!'''=Non è stato possibile stabilire la connessione. +'''Click 'Done' to return to the menu.'''=Fate clic su “Done” (Fatto) per tornare al menu. +'''is connected to SmartThings'''=connesso a SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=disconnesso da SmartThings. Le credenziali di accesso sono state modificate o sono andate perse. Andate alla SmartApp di Ecobee (Connect) e inserite nuovamente le credenziali di accesso all'account. +'''Your Ecobee thermostat '''=Il termostato Ecobee diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/ko-KR.properties b/smartapps/smartthings/ecobee-connect.src/i18n/ko-KR.properties new file mode 100644 index 0000000..71b56d1 --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/ko-KR.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Ecobee 온도조절기를 SmartThings에 연결하세요. +'''ecobee'''=Ecobee +'''You are connected.'''=연결되었습니다. +'''Click to enter Ecobee Credentials'''=Ecobee 로그인 정보를 입력하려면 클릭하세요 +'''Login'''=로그인 +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Ecobee 서비스에 로그인하여 SmartThings를 사용할 수 있도록 인증하려면 아래를 누르세요. 2페이지에서 아래로 스크롤한 후 [허용]을 누르세요. +'''ecobee'''=Ecobee +'''Select Your Thermostats'''=온도조절기 선택 +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Ecobee 계정에 등록된 Ecobee 온도조절기 목록을 확인하고 SmartThings에 연결할 기기를 선택하려면 아래를 누르세요. +'''Tap to choose'''=눌러서 선택 +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Ecobee 계정에 등록된 Ecobee 센서 목록을 확인하고 SmartThings에 연결할 기기를 선택하려면 아래를 누르세요. +'''Tap to choose'''=눌러서 선택 +'''Select Ecobee Sensors ({{numFound}} found)'''=Ecobee 센서 선택 ({{numFound}}개 찾음) +'''Your ecobee Account is now connected to SmartThings!'''=Ecobee 계정이 SmartThings에 연결되었습니다! +'''Click 'Done' to finish setup.'''=설정을 완료하려면 [완료]를 클릭하세요. +'''The connection could not be established!'''=연결을 실행할 수 없습니다! +'''Click 'Done' to return to the menu.'''=메뉴로 돌아가려면 [완료]를 클릭하세요. +'''is connected to SmartThings'''=이(가) SmartThings에 연결되었습니다 +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=이(가) SmartThings에서 연결 해제되었습니다. 로그인 정보가 변경되었거나 유실되었습니다. Ecobee (연결) 스마트앱에서 계정의 로그인 정보를 다시 입력하세요. +'''Your Ecobee thermostat '''=Ecobee 온도조절기 diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/nl-NL.properties b/smartapps/smartthings/ecobee-connect.src/i18n/nl-NL.properties new file mode 100644 index 0000000..1995a00 --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/nl-NL.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Verbind uw Ecobee-thermostaat met SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=U bent verbonden. +'''Click to enter Ecobee Credentials'''=Klik om Ecobee-inloggegevens in te voeren +'''Login'''=Inloggen +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Tik hieronder om in te loggen bij uw ecobee-service en toegang door SmartThings toe te staan. Scrol naar beneden op pagina 2 en druk op de knop Allow (Toestaan). +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Selecteer uw thermostaten +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Tik hieronder om de lijst met ecobee-thermostaten in uw ecobee-account weer te geven en de apparaten te selecteren die u wilt verbinden met SmartThings. +'''Tap to choose'''=Tik om te kiezen +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Tik hieronder om de lijst met ecobee-sensoren in uw ecobee-account weer te geven en de apparaten te selecteren die u wilt verbinden met SmartThings. +'''Tap to choose'''=Tik om te kiezen +'''Select Ecobee Sensors ({{numFound}} found)'''=Selecteer Ecobee-sensoren ({{numFound}} gevonden) +'''Your ecobee Account is now connected to SmartThings!'''=Uw ecobee-account is nu verbonden met SmartThings. +'''Click 'Done' to finish setup.'''=Klik op Done (Gereed) om het instellen te voltooien. +'''The connection could not be established!'''=Er kan geen verbinding worden gemaakt. +'''Click 'Done' to return to the menu.'''=Klik op Done (Gereed) om terug te gaan naar het menu. +'''is connected to SmartThings'''=is verbonden met SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=-verbinding met SmartThings is verbroken, omdat de inloggegevens zijn gewijzigd of verloren zijn gegaan. Ga naar de Ecobee (Connect) SmartApp en voer de inloggegevens voor uw account opnieuw in. +'''Your Ecobee thermostat '''=Uw Ecobee-thermostaat diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/no-NO.properties b/smartapps/smartthings/ecobee-connect.src/i18n/no-NO.properties new file mode 100644 index 0000000..612517b --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/no-NO.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Koble Ecobee-termostaten til SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=Du er tilkoblet. +'''Click to enter Ecobee Credentials'''=Klikk for å angi Ecobee-informasjon +'''Login'''=Logg på +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Trykk nedenfor for å logge på ecobee-tjenesten og godkjenne SmartThings-tilgang. Pass på å bla ned på side 2 og trykke på Allow (Tillat)-knappen. +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Velg termostatene dine +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Trykk nedenfor for å se listen over ecobee-termostatene som er tilgjengelige i ecobee-kontoen din, og velg de du vil koble til SmartThings. +'''Tap to choose'''=Trykk for å velge +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Trykk nedenfor for å se listen over ecobee-sensorene som er tilgjengelige i ecobee-kontoen din, og velg de du vil koble til SmartThings. +'''Tap to choose'''=Trykk for å velge +'''Select Ecobee Sensors ({{numFound}} found)'''=Velg Ecobee-sensorer (fant {{numFound}}) +'''Your ecobee Account is now connected to SmartThings!'''=ecobee-kontoen din er nå koblet til SmartThings! +'''Click 'Done' to finish setup.'''=Klikk på Done (Ferdig) for å fullføre oppsettet. +'''The connection could not be established!'''=Kunne ikke opprette tilkoblingen! +'''Click 'Done' to return to the menu.'''=Klikk på Done (Ferdig) for å gå tilbake til menyen. +'''is connected to SmartThings'''=er koblet til SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=er koblet fra SmartThings fordi tilgangsinformasjonen ble endret eller mistet. Gå til Ecobee (Connect) SmartApp, og angi påloggingsinformasjonen for kontoen på nytt. +'''Your Ecobee thermostat '''=Ecobee-termostaten diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/pl-PL.properties b/smartapps/smartthings/ecobee-connect.src/i18n/pl-PL.properties new file mode 100644 index 0000000..be1331a --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/pl-PL.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Połącz termostat Ecobee ze SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=Połączono. +'''Click to enter Ecobee Credentials'''=Kliknij, aby wprowadzić poświadczenia Ecobee +'''Login'''=Logowanie +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Dotknij poniżej, aby zalogować się do usługi ecobee i autoryzować dostęp SmartThings. Przewiń w dół na stronie 2 i naciśnij przycisk „Allow” (Zezwól). +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Wybierz termostaty +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Dotknij poniżej, aby wyświetlić listę termostatów ecobee dostępnych na koncie ecobee, i wybierz te, które chcesz połączyć ze SmartThings. +'''Tap to choose'''=Dotknij, aby wybrać +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Dotknij poniżej, aby wyświetlić listę czujników ecobee dostępnych na koncie ecobee, i wybierz te, które chcesz połączyć ze SmartThings. +'''Tap to choose'''=Dotknij, aby wybrać +'''Select Ecobee Sensors ({{numFound}} found)'''=Wybierz czujniki Ecobee (znaleziono {{numFound}}) +'''Your ecobee Account is now connected to SmartThings!'''=Konto ecobee jest teraz połączone ze SmartThings. +'''Click 'Done' to finish setup.'''=Kliknij opcję „Done” (Gotowe), aby ukończyć instalację. +'''The connection could not be established!'''=Nie można ustanowić połączenia. +'''Click 'Done' to return to the menu.'''=Kliknij opcję „Done” (Gotowe), aby powrócić do menu. +'''is connected to SmartThings'''=jest połączony ze SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=jest odłączony od SmartThings, ponieważ poświadczenie dostępu zostało zmienione lub utracone. Przejdź do aplikacji Ecobee (Connect) SmartApp i wprowadź ponownie poświadczenia logowania konta. +'''Your Ecobee thermostat '''=Termostat Ecobee diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/pt-BR.properties b/smartapps/smartthings/ecobee-connect.src/i18n/pt-BR.properties new file mode 100644 index 0000000..cc8d54b --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/pt-BR.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Conecte seu termostato Ecobee ao SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=Você está conectado. +'''Click to enter Ecobee Credentials'''=Clique para inserir as credenciais do Ecobee +'''Login'''=Conectar +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Toque abaixo para entrar no serviço ecobee e autorizar o acesso ao SmartThings. Certifique-se de rolar para baixo na página 2 e pressionar o botão 'Allow' (Permitir). +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Selecionar seus termostatos +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Toque abaixo para ver a lista de termostatos ecobee disponíveis na sua conta ecobee e selecione os que deseja conectar ao SmartThings. +'''Tap to choose'''=Tocar para escolher +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Toque abaixo para ver a lista de sensores ecobee disponíveis na sua conta ecobee e selecione os que deseja conectar ao SmartThings. +'''Tap to choose'''=Tocar para escolher +'''Select Ecobee Sensors ({{numFound}} found)'''=Selecionar sensores Ecobee ({{numFound}} encontrado(s)) +'''Your ecobee Account is now connected to SmartThings!'''=Agora sua conta ecobee está conectada ao SmartThings! +'''Click 'Done' to finish setup.'''=Clique em 'Done' (Concluído) para concluir a configuração. +'''The connection could not be established!'''=Não foi possível estabelecer a conexão! +'''Click 'Done' to return to the menu.'''=Clique em 'Done' (Concluído) para retornar ao menu. +'''is connected to SmartThings'''=está conectado ao SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=foi desconectado do SmartThings, pois a credencial de acesso foi alterada ou perdida. Vá para Ecobee (Connect) SmartApp e insira novamente suas credenciais de acesso à conta. +'''Your Ecobee thermostat '''=Seu termostato Ecobee diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/pt-PT.properties b/smartapps/smartthings/ecobee-connect.src/i18n/pt-PT.properties new file mode 100644 index 0000000..ef37cd5 --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/pt-PT.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Ligue o seu termóstato Ecobee ao SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=Está ligado. +'''Click to enter Ecobee Credentials'''=Clique para introduzir as Credenciais da Ecobee +'''Login'''=Iniciar Sessão +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Toque abaixo para iniciar sessão no serviço ecobee e autorizar o acesso ao SmartThings. Certifique-se de que se desloca para baixo na página 2 e prime o botão "Allow" (Permitir). +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Seleccionar os seus Termóstatos +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Toque abaixo para ver a lista de termóstatos da ecobee disponíveis na sua conta ecobee e seleccione aqueles que pretende ligar ao SmartThings. +'''Tap to choose'''=Toque para escolher +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Toque abaixo para ver a lista de sensores da ecobee disponíveis na sua conta ecobee e seleccione aqueles que pretende ligar ao SmartThings. +'''Tap to choose'''=Toque para escolher +'''Select Ecobee Sensors ({{numFound}} found)'''=Seleccionar sensores da Ecobee ({{numFound}} encontrado) +'''Your ecobee Account is now connected to SmartThings!'''=Agora, a sua Conta ecobee está ligada ao SmartThings! +'''Click 'Done' to finish setup.'''=Clique em "Done" (Concluir) para terminar a configuração. +'''The connection could not be established!'''=Não foi possível estabelecer a ligação! +'''Click 'Done' to return to the menu.'''=Clique em "Done" (Concluir) para regressar ao menu. +'''is connected to SmartThings'''=está ligado ao SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=foi desligado do SmartThings, porque a credencial de acesso foi alterada ou perdida. Vá para Ecobee (Connect) SmartApp e introduza novamente as suas credenciais de início de sessão na conta. +'''Your Ecobee thermostat '''=O seu termóstato Ecobee diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/ro-RO.properties b/smartapps/smartthings/ecobee-connect.src/i18n/ro-RO.properties new file mode 100644 index 0000000..73fbd41 --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/ro-RO.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Conectați termostatul Ecobee la SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=Sunteți conectat. +'''Click to enter Ecobee Credentials'''=Faceți clic pentru a introduce acreditările Ecobee +'''Login'''=Conectare +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Atingeți mai jos pentru a vă conecta la serviciul ecobee și a autoriza accesul la SmartThings. Asigurați-vă că ați derulat în jos până la pagina 2 și apăsați butonul „Allow” (Permitere). +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Selectați termostatele +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Atingeți mai jos pentru a vizualiza o listă de termostate ecobee disponibile în contul dvs. ecobee și selectați-le pe cele pe care doriți să le conectați la SmartThings. +'''Tap to choose'''=Atingeți pentru a selecta +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Atingeți mai jos pentru a vizualiza o listă de senzori ecobee disponibili în contul dvs. ecobee și selectați-i pe cei pe care doriți să îi conectați la SmartThings. +'''Tap to choose'''=Atingeți pentru a selecta +'''Select Ecobee Sensors ({{numFound}} found)'''=Selectare senzori Ecobee ({{numFound}} găsiți) +'''Your ecobee Account is now connected to SmartThings!'''=Contul dvs. ecobee este acum conectat la SmartThings! +'''Click 'Done' to finish setup.'''=Faceți clic pe „Done” (Efectuat) pentru a finaliza configurarea. +'''The connection could not be established!'''=Nu a putut fi stabilită conexiunea! +'''Click 'Done' to return to the menu.'''=Faceți clic pe „Done” (Efectuat) pentru a reveni la meniu. +'''is connected to SmartThings'''=este conectat la SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=este deconectat de la SmartThings, deoarece acreditările de acces au fost schimbate sau pierdute. Accesați aplicația Ecobee (Connect) SmartApp și reintroduceți acreditările de conectare la cont. +'''Your Ecobee thermostat '''=Termostatul dvs. Ecobee diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/ru-RU.properties b/smartapps/smartthings/ecobee-connect.src/i18n/ru-RU.properties new file mode 100644 index 0000000..2c7ab8e --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/ru-RU.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Подключите свой термостат Ecobee к SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=Подключено. +'''Click to enter Ecobee Credentials'''=Нажмите для ввода учетных данных Ecobee +'''Login'''=Вход +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Коснитесь ниже, чтобы войти в службу ecobee и предоставить доступ SmartThings. Обязательно прокрутите страницу 2 до самого низа и нажмите кнопку «Разрешить». +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Выберите свои термостаты +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Коснитесь ниже, чтобы отобразить список доступных термостатов ecobee в вашей учетной записи ecobee, и выберите те, которые нужно подключить к SmartThings. +'''Tap to choose'''=Коснитесь, чтобы выбрать +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Коснитесь ниже, чтобы отобразить список доступных датчиков ecobee в вашей учетной записи ecobee, и выберите те, которые нужно подключить к SmartThings. +'''Tap to choose'''=Коснитесь, чтобы выбрать +'''Select Ecobee Sensors ({{numFound}} found)'''=Выбрать датчики Ecobee (найдено {{numFound}}) +'''Your ecobee Account is now connected to SmartThings!'''=Теперь ваша учетная запись ecobee подключена к SmartThings! +'''Click 'Done' to finish setup.'''=Для завершения настройки нажмите «Готово». +'''The connection could not be established!'''=Не удалось установить соединение! +'''Click 'Done' to return to the menu.'''=Чтобы вернуться в меню, нажмите «Готово». +'''is connected to SmartThings'''=подключено к SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=отключено от SmartThings, поскольку данные для доступа были изменены или потеряны. Перейдите в Ecobee (Подключить) SmartApp и повторно введите регистрационные данные своей учетной записи. +'''Your Ecobee thermostat '''=Ваш термостат Ecobee diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/sk-SK.properties b/smartapps/smartthings/ecobee-connect.src/i18n/sk-SK.properties new file mode 100644 index 0000000..8b40983 --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/sk-SK.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Pripojte termostat Ecobee k systému SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=Ste pripojení. +'''Click to enter Ecobee Credentials'''=Kliknite a zadajte poverenia pre Ecobee +'''Login'''=Prihlásiť sa +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Ťuknutím nižšie sa prihláste k službe ecobee a autorizujte prístup do systému SmartThings. Prejdite nadol na stránku 2 a stlačte tlačidlo Allow (Povoliť). +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Vyberte termostaty +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Ťuknutím nižšie môžete zobraziť zoznam termostatov ecobee dostupných vo vašom konte ecobee a vybrať tie, ktoré chcete pripojiť k systému SmartThings. +'''Tap to choose'''=Ťuknutím vyberte +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Ťuknutím nižšie môžete zobraziť zoznam senzorov ecobee dostupných vo vašom konte ecobee a vybrať tie, ktoré chcete pripojiť k systému SmartThings. +'''Tap to choose'''=Ťuknutím vyberte +'''Select Ecobee Sensors ({{numFound}} found)'''=Vyberte senzory Ecobee (nájdené: {{numFound}}) +'''Your ecobee Account is now connected to SmartThings!'''=Vaše konto ecobee je teraz prepojené so systémom SmartThings. +'''Click 'Done' to finish setup.'''=Kliknutím na tlačidlo Done (Hotovo) dokončite inštaláciu. +'''The connection could not be established!'''=Nepodarilo sa nadviazať spojenie. +'''Click 'Done' to return to the menu.'''=Kliknutím na tlačidlo Done (Hotovo) sa vráťte do menu. +'''is connected to SmartThings'''=je pripojený k systému SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=je odpojený od systému SmartThings, pretože prístupové poverenia boli zmenené alebo stratené. Prejdite do aplikácie Ecobee (Connect) SmartApp a znova zadajte prihlasovacie poverenia pre konto. +'''Your Ecobee thermostat '''=Váš termostat Ecobee diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/sl-SI.properties b/smartapps/smartthings/ecobee-connect.src/i18n/sl-SI.properties new file mode 100644 index 0000000..457ec7f --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/sl-SI.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Povežite termostat Ecobee s storitvijo SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=Povezani ste. +'''Click to enter Ecobee Credentials'''=Kliknite za vnos poverilnic Ecobee +'''Login'''=Prijava +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Pritisnite spodaj, da se prijavite v storitev ecobee in odobrite dostop do storitve SmartThings. Pomaknite se na 2. stran in pritisnite gumb »Allow« (Dovoli). +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Izberite svoje termostate +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Pritisnite spodaj za prikaz seznama termostatov ecobee, ki so na voljo v vašem računu ecobee, in izberite tiste, ki jih želite povezati s storitvijo SmartThings. +'''Tap to choose'''=Pritisnite za izbiranje +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Pritisnite spodaj za prikaz seznama senzorjev ecobee, ki so na voljo v vašem računu ecobee, in izberite tiste, ki jih želite povezati s storitvijo SmartThings. +'''Tap to choose'''=Pritisnite za izbiranje +'''Select Ecobee Sensors ({{numFound}} found)'''=Izberite senzorje Ecobee (št. najdenih: {{numFound}}) +'''Your ecobee Account is now connected to SmartThings!'''=Vaš račun ecobee je zdaj povezan s storitvijo SmartThings! +'''Click 'Done' to finish setup.'''=Kliknite »Done« (Končano), da zaključite nastavitev. +'''The connection could not be established!'''=Povezave ni bilo mogoče vzpostaviti! +'''Click 'Done' to return to the menu.'''=Kliknite »Done« (Končano), da se vrnete v meni. +'''is connected to SmartThings'''=je povezan s storitvijo SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=ni povezan s storitvijo SmartThings, ker so bile poverilnice za dostop spremenjene ali izgubljene. Pojdite v aplikacijo Ecobee (Connect) SmartApp in znova vnesite poverilnice za prijavo v račun. +'''Your Ecobee thermostat '''=Vaš termostat Ecobee diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/sq-AL.properties b/smartapps/smartthings/ecobee-connect.src/i18n/sq-AL.properties new file mode 100644 index 0000000..ec3a107 --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/sq-AL.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Lidh termostatin Ecobee me SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=Je lidhur. +'''Click to enter Ecobee Credentials'''=Kliko për të futur kredencialet Ecobee +'''Login'''=Login +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Trokit më poshtë për t’u loguar në shërbimin ecobee dhe autorizuar aksesin në SmartThings. Sigurohu që të lundrosh poshtë në faqen 2 dhe të shtypësh butonin ‘Allow’ (Lejo). +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Përzgjidh termostatet e tua +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Trokit më poshtë për të parë listën e termostateve ecobee që janë në dispozicion në llogarinë tënde ecobee dhe përzgjidh ato që dëshiron të lidhen me SmartThings. +'''Tap to choose'''=Trokit për të zgjedhur +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Trokit më poshtë për të parë listën e sensorëve ecobee që janë në dispozicion në llogarinë tënde ecobee dhe përzgjidh ato që dëshiron të lidhen me SmartThings. +'''Tap to choose'''=Trokit për të zgjedhur +'''Select Ecobee Sensors ({{numFound}} found)'''=Përzgjidh sensorët Ecobee (u gjet {{numFound}}) +'''Your ecobee Account is now connected to SmartThings!'''=Llogaria jote ecobee tani është lidhur me SmartThings! +'''Click 'Done' to finish setup.'''=Kliko mbi ‘Done’ (U krye) për ta mbaruar konfigurimin. +'''The connection could not be established!'''=Lidhja nuk u vendos dot! +'''Click 'Done' to return to the menu.'''=Kliko mbi ‘Done’ (U krye) për t’u kthyer në meny. +'''is connected to SmartThings'''=është lidhur me SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=është shkëputur nga SmartThings, sepse kredenciali i aksesit ka ndryshuar ose ka humbur. Shko te Ecobee (Connect) SmartApp dhe futi sërish kredencialet e logimit në llogari. +'''Your Ecobee thermostat '''=Termostati yt Ecobee diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/sr-RS.properties b/smartapps/smartthings/ecobee-connect.src/i18n/sr-RS.properties new file mode 100644 index 0000000..9433af6 --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/sr-RS.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Povežite Ecobee termostat na SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=Povezani ste. +'''Click to enter Ecobee Credentials'''=Kliknite da biste uneli Ecobee akreditive +'''Login'''=Login (Prijava) +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Kucnite ispod da biste se prijavili na uslugu ecobee i odobrili pristup aplikaciji SmartThings. Obavezno listajte nadole do stranice broj 2 i pritisnite dugme „Allow” (Dozvoli). +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Izaberite termostate +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Kucnite ispod da biste videli listu dostupnih ecobee termostata na svom ecobee nalogu i izaberite one koje želite da povežete na SmartThings. +'''Tap to choose'''=Kucnite da biste odabrali +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Kucnite ispod da biste videli listu dostupnih senzora na svom ecobee nalogu i izaberite one koje želite da povežete na SmartThings. +'''Tap to choose'''=Kucnite da biste odabrali +'''Select Ecobee Sensors ({{numFound}} found)'''=Izaberite Ecobee senzore ({{numFound}} pronađeno) +'''Your ecobee Account is now connected to SmartThings!'''=Vaš ecobee nalog je sada povezan na SmartThings! +'''Click 'Done' to finish setup.'''=Kliknite na „Done” (Gotovo) za kraj konfiguracije. +'''The connection could not be established!'''=Veza nije uspostavljena! +'''Click 'Done' to return to the menu.'''=Kliknite na „Done” (Gotovo) da biste se vratili na meni. +'''is connected to SmartThings'''=je povezan na SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=je prekinuo vezu sa aplikacijom SmartThings zato što su akreditivi za pristup promenjeni ili izgubljeni. Idite na aplikaciju Ecobee (Connect) SmartApp i ponovo unesite akreditive za prijavljivanje na nalog. +'''Your Ecobee thermostat '''=Vaš Ecobee termostat diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/sv-SE.properties b/smartapps/smartthings/ecobee-connect.src/i18n/sv-SE.properties new file mode 100644 index 0000000..e50ad4c --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/sv-SE.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Anslut din Ecobee-termostat till SmartThings. +'''ecobee'''=ecobee +'''You are connected.'''=Du är ansluten. +'''Click to enter Ecobee Credentials'''=Klicka för att ange dina Ecobee-inloggningsuppgifter +'''Login'''=Logga in +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Tryck nedan för att logga in på ecobee-tjänsten och ge SmartThings åtkomst. Rulla ned till sidan 2 och tryck på knappen Allow (Tillåt). +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Välj dina termostater +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Tryck nedan om du vill se listan med ecobee-termostater som är tillgängliga i ditt ecobee-konto och välj dem du vill ansluta till SmartThings. +'''Tap to choose'''=Tryck för att välja +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Tryck nedan om du vill se listan med ecobee-givare som är tillgängliga i ditt ecobee-konto och välj dem du vill ansluta till SmartThings. +'''Tap to choose'''=Tryck för att välja +'''Select Ecobee Sensors ({{numFound}} found)'''=Välj Ecobee-givare ({{numFound}} hittades) +'''Your ecobee Account is now connected to SmartThings!'''=Ditt ecobee-konto är nu anslutet till SmartThings! +'''Click 'Done' to finish setup.'''=Klicka på Done (Klart) för att slutföra konfigurationen. +'''The connection could not be established!'''=Det gick inte att upprätta anslutningen! +'''Click 'Done' to return to the menu.'''=Klicka på Done (Klart) för att återgå till menyn. +'''is connected to SmartThings'''=är ansluten till SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=är frånkopplad från SmartThings, eftersom inloggningsuppgifterna har ändrats eller gått förlorade. Starta Ecobee (Connect) SmartApp och ange kontots inloggningsuppgifter igen. +'''Your Ecobee thermostat '''=Din Ecobee-termostat diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/th-TH.properties b/smartapps/smartthings/ecobee-connect.src/i18n/th-TH.properties new file mode 100644 index 0000000..8f5294c --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/th-TH.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=เชื่อมต่อตัวควบคุมอุณหภูมิ Ecobee ของคุณเข้ากับ SmartThings +'''ecobee'''=Ecobee +'''You are connected.'''=คุณได้เชื่อมต่อแล้ว +'''Click to enter Ecobee Credentials'''=คลิกเพื่อใส่ ข้อมูลยืนยันตัวตน Ecobee +'''Login'''=เข้าสู่ระบบ +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=แตะด้านล่างเพื่อเข้าสู่บริการ Ecobee และอนุญาตการเข้าถึงของ SmartThings ดูให้แน่ใจว่าได้เลื่อนลงมาที่หน้า 2 แล้วกดปุ่ม 'อนุญาต' +'''ecobee'''=Ecobee +'''Select Your Thermostats'''=เลือกตัวควบคุมอุณหภูมิของคุณ +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=แตะที่ด้านล่างเพื่อดูรายการตัวควบคุมอุณหภูมิ Ecobee ที่มีอยู่ในบัญชีผู้ใช้ Ecobee ของคุณ และเลือกตัวควบคุมอุณหภูมิที่คุณต้องการจะเชื่อมต่อกับ SmartThings +'''Tap to choose'''=แตะเพื่อเลือก +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=แตะที่ด้านล่างเพื่อดูรายการเซ็นเซอร์ Ecobee ที่มีอยู่ในบัญชีผู้ใช้ Ecobee ของคุณ และเลือกเซ็นเซอร์ที่คุณต้องการจะเชื่อมต่อกับ SmartThings +'''Tap to choose'''=แตะเพื่อเลือก +'''Select Ecobee Sensors ({{numFound}} found)'''=เลือกเซ็นเซอร์ Ecobee ({{numFound}} found) +'''Your ecobee Account is now connected to SmartThings!'''=ตอนนี้บัญชีผู้ใช้ Ecobee ของคุณเชื่อมต่อกับ SmartThings แล้ว +'''Click 'Done' to finish setup.'''=คลิก 'เสร็จสิ้น' เพื่อทำการตั้งค่าให้เสร็จสิ้น +'''The connection could not be established!'''=ไม่สามารถสร้างการเชื่อมต่อได้! +'''Click 'Done' to return to the menu.'''=คลิก 'เสร็จสิ้น' เพื่อกลับไปยังเมนู +'''is connected to SmartThings'''={{deviceName}} เชื่อมต่อกับ SmartThings แล้ว +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''={{deviceName}} ถูกตัดการเชื่อมต่อจาก SmartThings เนื่องจากข้อมูลการเข้าถึงถูกเปลี่ยนแปลงหรือหายไป กรุณาไปที่ Ecobee (การเชื่อมต่อ) SmartApp และใส่ข้อมูลยืนยันตัวตนการเข้าสู่บัญชีผู้ใช้ของคุณอีกครั้ง +'''Your Ecobee thermostat '''=ตัวควบคุมอุณหภูมิ Ecobee ของคุณ diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/tr-TR.properties b/smartapps/smartthings/ecobee-connect.src/i18n/tr-TR.properties new file mode 100644 index 0000000..449b848 --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/tr-TR.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=Ecobee termostatınızı SmartThings'e bağlayın. +'''ecobee'''=ecobee +'''You are connected.'''=Bağlantı kurdunuz. +'''Click to enter Ecobee Credentials'''=Ecobee Kimlik Bilgilerinizi girmek için tıklayın +'''Login'''=Oturum aç +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=Ecobee servisinde oturum açmak ve SmartThings erişimine izin vermek için aşağıya dokunun. Ekranı 2. sayfaya kaydırdığınızdan emin olun ve 'İzin Ver' tuşuna basın. +'''ecobee'''=ecobee +'''Select Your Thermostats'''=Termostatlarınızı Seçin +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=Ecobee hesabınızda mevcut olan ecobee termostatlarının listesini görüntülemek için aşağıya dokunun ve SmartThings'e bağlamak istediklerinizi seçin. +'''Tap to choose'''= seçmek için dokunun +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=Ecobee hesabınızda mevcut olan ecobee sensörlerinin listesini görüntülemek için aşağıya dokunun ve SmartThings'e bağlamak istediklerinizi seçin. +'''Tap to choose'''= seçmek için dokunun +'''Select Ecobee Sensors ({{numFound}} found)'''=Ecobee Sensörlerini seçin ({{numFound}} bulundu) +'''Your ecobee Account is now connected to SmartThings!'''=Ecobee Hesabınız artık SmartThings'e bağlandı! +'''Click 'Done' to finish setup.'''=Kurulumu bitirmek için 'Bitti' öğesine tıklayın. +'''The connection could not be established!'''=Bağlantı kurulamadı! +'''Click 'Done' to return to the menu.'''=Menüye dönmek için 'Bitti' öğesine tıklayın. +'''is connected to SmartThings'''={{cihazİsmi}} SmartThings'e bağlandı +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=Erişim kimlik doğruları değiştirildiğinden veya kaybolduğundan {{cihazİsmi}} ile SmartThings arasındaki bağlantı kesildi. Lütfen Ecobee (Connect) SmartApp'e gidin ve hesabınızın oturum açma kimlik bilgilerini tekrar girin. +'''Your Ecobee thermostat '''=Ecobee termostatınız diff --git a/smartapps/smartthings/ecobee-connect.src/i18n/zh-CN.properties b/smartapps/smartthings/ecobee-connect.src/i18n/zh-CN.properties new file mode 100644 index 0000000..dca3bec --- /dev/null +++ b/smartapps/smartthings/ecobee-connect.src/i18n/zh-CN.properties @@ -0,0 +1,20 @@ +'''Connect your Ecobee thermostat to SmartThings.'''=将 Ecobee 恒温器连接至 SmartThings。 +'''ecobee'''=ecobee +'''You are connected.'''=已连接。 +'''Click to enter Ecobee Credentials'''=点击以输入 Ecobee 凭据 +'''Login'''=登录 +'''Tap below to log in to the ecobee service and authorize SmartThings access. Be sure to scroll down on page 2 and press the 'Allow' button.'''=点击下方以登录 ecobee 服务并授予 SmartThings 访问权限。务必在第 2 页上向下滚动,然后按下“允许”按钮。 +'''ecobee'''=ecobee +'''Select Your Thermostats'''=选择恒温器 +'''Tap below to see the list of ecobee thermostats available in your ecobee account and select the ones you want to connect to SmartThings.'''=点击下方以查看 ecobee 帐户中可用 ecobee 恒温器的列表,然后选择要连接至 SmartThings 的恒温器。 +'''Tap to choose'''=点击以选择 +'''Tap below to see the list of ecobee sensors available in your ecobee account and select the ones you want to connect to SmartThings.'''=点击下方以查看 ecobee 帐户中可用 ecobee 传感器的列表,然后选择要连接至 SmartThings 的传感器。 +'''Tap to choose'''=点击以选择 +'''Select Ecobee Sensors ({{numFound}} found)'''=选择 Ecobee 传感器 (发现 {{numFound}} 个) +'''Your ecobee Account is now connected to SmartThings!'''=ecobee 帐户现在已连接至 SmartThings! +'''Click 'Done' to finish setup.'''=单击“完成”以完成设置。 +'''The connection could not be established!'''=无法建立连接! +'''Click 'Done' to return to the menu.'''=单击“完成”返回菜单。 +'''is connected to SmartThings'''=已连接至 SmartThings +'''is disconnected from SmartThings, because the access credential changed or was lost. Please go to the Ecobee (Connect) SmartApp and re-enter your account login credentials.'''=已从 SmartThings 断开,因为访问凭据已更改或丢失。请转到 Ecobee (连接) SmartApp,然后重新输入您的帐户登录凭据。 +'''Your Ecobee thermostat '''=您的 Ecobee 恒温器 diff --git a/smartapps/smartthings/hue-connect.src/hue-connect.groovy b/smartapps/smartthings/hue-connect.src/hue-connect.groovy index 621d0d0..8870987 100644 --- a/smartapps/smartthings/hue-connect.src/hue-connect.groovy +++ b/smartapps/smartthings/hue-connect.src/hue-connect.groovy @@ -17,14 +17,14 @@ */ definition( - name: "Hue (Connect)", - namespace: "smartthings", - author: "SmartThings", - description: "Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Adjust colors by going to the Thing detail screen for your Hue lights (tap the gear on Hue tiles).\n\nPlease update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.", - category: "SmartThings Labs", - iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/hue.png", - iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/hue@2x.png", - singleInstance: true + name: "Hue (Connect)", + namespace: "smartthings", + author: "SmartThings", + description: "Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Adjust colors by going to the Thing detail screen for your Hue lights (tap the gear on Hue tiles).\n\nPlease update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.", + category: "SmartThings Labs", + iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/hue.png", + iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/hue@2x.png", + singleInstance: true ) preferences { @@ -85,7 +85,8 @@ def bridgeDiscovery(params=[:]) } return dynamicPage(name:"bridgeDiscovery", title:"Discovery Started!", nextPage:"bridgeBtnPush", refreshInterval:refreshInterval, uninstall: true) { - section("Please wait while we discover your Hue Bridge. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.") { + section("Please wait while we discover your Hue Bridge. Kindly note that you must first configure your Hue Bridge and Lights using the Philips Hue application. " + + "Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.") { input "selectedHue", "enum", required:false, title:"Select Hue Bridge (${numFound} found)", multiple:false, options:options, submitOnChange: true } } @@ -172,18 +173,34 @@ def bulbDiscovery() { if (existingLightsDescription.isEmpty()) { existingLightsDescription += it.value } else { - existingLightsDescription += ", ${it.value}" + existingLightsDescription += ", ${it.value}" } } } - return dynamicPage(name:"bulbDiscovery", title:"Light Discovery Started!", nextPage:"", refreshInterval:refreshInterval, install:true, uninstall: true) { - section("Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.") { - input "selectedBulbs", "enum", required:false, title:"Select Hue Lights to add (${numFound} found)", multiple:true, submitOnChange: true, options:newLights - paragraph title: "Previously added Hue Lights (${existingLights.size()} added)", existingLightsDescription + if (bulbRefreshCount > 200 && numFound == 0) { + // Time out after 10 minutes + state.inBulbDiscovery = false + bulbRefreshCount = 0 + return dynamicPage(name:"bulbDiscovery", title:"Light Discovery Failed!", nextPage:"", refreshInterval:0, install:true, uninstall: true) { + section("Failed to discover any lights, please try again later. Click Done to exit.") { + //input "selectedBulbs", "enum", required:false, title:"Select Hue Lights to add (${numFound} found)", multiple:true, submitOnChange: true, options:newLights + paragraph title: "Previously added Hue Lights (${existingLights.size()} added)", existingLightsDescription + } + section { + href "bridgeDiscovery", title: title, description: "", state: selectedHue ? "complete" : "incomplete", params: [override: true] + } } - section { - href "bridgeDiscovery", title: title, description: "", state: selectedHue ? "complete" : "incomplete", params: [override: true] + + } else { + return dynamicPage(name:"bulbDiscovery", title:"Light Discovery Started!", nextPage:"", refreshInterval:refreshInterval, install:true, uninstall: true) { + section("Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.") { + input "selectedBulbs", "enum", required:false, title:"Select Hue Lights to add (${numFound} found)", multiple:true, submitOnChange: true, options:newLights + paragraph title: "Previously added Hue Lights (${existingLights.size()} added)", existingLightsDescription + } + section { + href "bridgeDiscovery", title: title, description: "", state: selectedHue ? "complete" : "incomplete", params: [override: true] + } } } } @@ -200,32 +217,32 @@ private sendDeveloperReq() { def token = app.id def host = getBridgeIP() sendHubCommand(new physicalgraph.device.HubAction([ - method: "POST", - path: "/api", - headers: [ - HOST: host - ], - body: [devicetype: "$token-0"]], "${selectedHue}", [callback: "usernameHandler"])) + method: "POST", + path: "/api", + headers: [ + HOST: host + ], + body: [devicetype: "$token-0"]], "${selectedHue}", [callback: "usernameHandler"])) } private discoverHueBulbs() { def host = getBridgeIP() sendHubCommand(new physicalgraph.device.HubAction([ - method: "GET", - path: "/api/${state.username}/lights", - headers: [ - HOST: host - ]], "${selectedHue}", [callback: "lightsHandler"])) + method: "GET", + path: "/api/${state.username}/lights", + headers: [ + HOST: host + ]], "${selectedHue}", [callback: "lightsHandler"])) } private verifyHueBridge(String deviceNetworkId, String host) { log.trace "Verify Hue Bridge $deviceNetworkId" sendHubCommand(new physicalgraph.device.HubAction([ - method: "GET", - path: "/description.xml", - headers: [ - HOST: host - ]], deviceNetworkId, [callback: "bridgeDescriptionHandler"])) + method: "GET", + path: "/description.xml", + headers: [ + HOST: host + ]], deviceNetworkId, [callback: "bridgeDescriptionHandler"])) } private verifyHueBridges() { @@ -383,7 +400,7 @@ def addBulbs() { log.debug "$dni in not longer paired to the Hue Bridge or ID changed" } } else { - //backwards compatable + //backwards compatable newHueBulb = bulbs.find { (app.id + "/" + it.id) == dni } d = addChildBulb(dni, "Extended Color Light", newHueBulb?.value?.name, newHueBulb?.value?.hub) d?.completedSetup = true @@ -407,7 +424,7 @@ def addBridge() { if(vbridge) { def d = getChildDevice(selectedHue) if(!d) { - // compatibility with old devices + // compatibility with old devices def newbridge = true childDevices.each { if (it.getDeviceDataByName("mac")) { @@ -455,8 +472,6 @@ def addBridge() { log.error "Failed to create Hue Bridge device" } } - } else { - log.debug "found ${d.displayName} with id $selectedHue already exists" } } } @@ -593,7 +608,7 @@ def locationHandler(evt) { log.trace "Location: $description" def hub = evt?.hubId - def parsedEvent = parseLanMessage(description) + def parsedEvent = parseLanMessage(description) parsedEvent << ["hub":hub] if (parsedEvent?.ssdpTerm?.contains("urn:schemas-upnp-org:device:basic:1")) { @@ -698,6 +713,9 @@ def doDeviceSync(){ log.warn "state.updating failed to clear" } + if (selectedHue) { + addBridge() + } convertBulbListToMap() poll() ssdpSubscribe() @@ -819,8 +837,7 @@ def parse(childDevice, description) { try { body = new groovy.json.JsonSlurper().parseText(bodyString) } catch (all) { - log.warn "Parsing Body failed - trying again..." - poll() + log.warn "Parsing Body failed" } if (body instanceof java.util.Map) { // get (poll) reponse @@ -844,7 +861,7 @@ private sendColorEvents(device, xy, hue, sat, ct, colormode = null) { def events = [:] // For now, only care about changing color temperature if requested by user - if (ct != null && (colormode == "ct" || (xy == null && hue == null && sat == null))) { + if (ct != null && ct != 0 && (colormode == "ct" || (xy == null && hue == null && sat == null))) { // for some reason setting Hue to their specified minimum off 153 yields 154, dealt with below // 153 (6500K) to 500 (2000K) def temp = (ct == 154) ? 6500 : Math.round(1000000 / ct) @@ -1136,7 +1153,7 @@ def setColorTemperature(childDevice, huesettings) { def ct = hueSettings == 6500 ? 153 : Math.round(1000000/huesettings) createSwitchEvent(childDevice, "on") put("lights/$id/state", [ct: ct, on: true]) - return "Setting color temperature to $percent" + return "Setting color temperature to $ct" } def setColor(childDevice, huesettings) { @@ -1211,7 +1228,7 @@ private poll() { def uri = "/api/${state.username}/lights/" log.debug "GET: $host$uri" sendHubCommand(new physicalgraph.device.HubAction("GET ${uri} HTTP/1.1\r\n" + - "HOST: ${host}\r\n\r\n", physicalgraph.device.Protocol.LAN, selectedHue)) + "HOST: ${host}\r\n\r\n", physicalgraph.device.Protocol.LAN, selectedHue)) } private isOnline(id) { @@ -1228,10 +1245,10 @@ private put(path, body) { log.debug "BODY: ${bodyJSON}" sendHubCommand(new physicalgraph.device.HubAction("PUT $uri HTTP/1.1\r\n" + - "HOST: ${host}\r\n" + - "Content-Length: ${length}\r\n" + - "\r\n" + - "${bodyJSON}", physicalgraph.device.Protocol.LAN, "${selectedHue}")) + "HOST: ${host}\r\n" + + "Content-Length: ${length}\r\n" + + "\r\n" + + "${bodyJSON}", physicalgraph.device.Protocol.LAN, "${selectedHue}")) } /* @@ -1252,7 +1269,7 @@ private getBridgeIP() { if (d) { if (d.getDeviceDataByName("networkAddress")) host = d.getDeviceDataByName("networkAddress") - else + else host = d.latestState('networkAddress').stringValue } if (host == null || host == "") { @@ -1342,7 +1359,7 @@ private void createSwitchEvent(childDevice, setSwitch, setLevel = null) { private colorPointsForModel(model = null) { def result = null switch (model) { - // Gamut A + // Gamut A case "LLC001": /* Monet, Renoir, Mondriaan (gen II) */ case "LLC005": /* Bloom (gen II) */ case "LLC006": /* Iris (gen III) */ @@ -1354,12 +1371,12 @@ private colorPointsForModel(model = null) { case "LLC010": /* Hue Living Colors Iris + */ result = [r:[x: 0.704f, y: 0.296f], g:[x: 0.2151f, y: 0.7106f], b:[x: 0.138f, y: 0.08f]]; break - // Gamut C + // Gamut C case "LLC020": /* Hue Go */ case "LST002": /* Hue LightStrips Plus */ result = [r:[x: 0.692f, y: 0.308f], g:[x: 0.17f, y: 0.7f], b:[x: 0.153f, y: 0.048f]]; break - // Gamut B + // Gamut B case "LCT001": /* Hue A19 */ case "LCT002": /* Hue BR30 */ case "LCT003": /* Hue GU10 */ @@ -1787,4 +1804,3 @@ def hsvToHex(hue, sat, value = 100){ return "#$r1$g1$b1" } - diff --git a/smartapps/smartthings/lifx-connect.src/i18n/ar-AE.properties b/smartapps/smartthings/lifx-connect.src/i18n/ar-AE.properties new file mode 100644 index 0000000..5e43d0e --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/ar-AE.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=يتيح لك استخدام مصابيح LIFX الذكية من خلال SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=النقر لإدخال بيانات اعتماد LIFX +'''Connect to LIFX'''=الاتصال بـ LIFX +'''Tap here to connect your LIFX account'''=النقر هنا لتوصيل حساب LIFX +'''Connect to LIFX'''=الاتصال بـ LIFX +'''Select your location'''=تحديد موقعك +'''Select location ({{count}} found)'''=تحديد الموقع (‎{{count}} found) +'''Your LIFX Account is now connected to SmartThings!'''=حساب LIFX متصل الآن بـ SmartThings! +'''Click 'Done' to finish setup.'''=انقر فوق ”تم“ لإنهاء الإعداد. +'''The connection could not be established!'''=يتعذر إنشاء الاتصال! +'''Click 'Done' to return to the menu.'''=انقر فوق ”تم“ للعودة إلى القائمة. +'''Your LIFX Account is already connected to SmartThings!'''=حساب LIFX متصل بالفعل بـ SmartThings! +'''Click 'Done' to finish setup.'''=انقر فوق ”تم“ لإنهاء الإعداد. +'''SmartThings Connection'''=اتصال SmartThings diff --git a/smartapps/smartthings/lifx-connect.src/i18n/bg-BG.properties b/smartapps/smartthings/lifx-connect.src/i18n/bg-BG.properties new file mode 100644 index 0000000..508727e --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/bg-BG.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Позволява да използвате интелигентни ел. крушки LIFX със SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Докоснете за въвеждане на идентификационни данни за LIFX +'''Connect to LIFX'''=Свързване към LIFX +'''Tap here to connect your LIFX account'''=Докоснете тук за свързване на вашия LIFX акаунт +'''Connect to LIFX'''=Свързване към LIFX +'''Select your location'''=Избор на местоположение +'''Select location ({{count}} found)'''=Избор на местоположение ({{count}} са намерени) +'''Your LIFX Account is now connected to SmartThings!'''=Вашият LIFX акаунт вече е свързан към SmartThings! +'''Click 'Done' to finish setup.'''=Щракнете върху Done (Готово), за да завършите настройката. +'''The connection could not be established!'''=Връзката не може да се осъществи! +'''Click 'Done' to return to the menu.'''=Щракнете върху Done (Готово), за да се върнете към менюто. +'''Your LIFX Account is already connected to SmartThings!'''=Вашият LIFX акаунт вече е свързан към SmartThings! +'''Click 'Done' to finish setup.'''=Щракнете върху Done (Готово), за да завършите настройката. +'''SmartThings Connection'''=Свързване на SmartThings diff --git a/smartapps/smartthings/lifx-connect.src/i18n/cs-CZ.properties b/smartapps/smartthings/lifx-connect.src/i18n/cs-CZ.properties new file mode 100644 index 0000000..2ebcfa0 --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/cs-CZ.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Umožní vám použít inteligentní žárovky LIFX se systémem SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Klepněte a zadejte přihlašovací údaje LIFX +'''Connect to LIFX'''=Připojit k LIFX +'''Tap here to connect your LIFX account'''=Klepnutím sem se připojíte k účtu LIFX +'''Connect to LIFX'''=Připojit k LIFX +'''Select your location'''=Vyberte vaši polohu +'''Select location ({{count}} found)'''=Vyberte polohu (nalezeno {{count}}) +'''Your LIFX Account is now connected to SmartThings!'''=Účet LIFX Account je nyní připojen k systému SmartThings! +'''Click 'Done' to finish setup.'''=Dokončete nastavení klepnutím na tlačítko „Done“ (Hotovo). +'''The connection could not be established!'''=Připojení nelze navázat! +'''Click 'Done' to return to the menu.'''=Klepnutím na tlačítko „Done“ (Hotovo) se vrátíte do menu. +'''Your LIFX Account is already connected to SmartThings!'''=Účet LIFX Account je již připojen k systému SmartThings! +'''Click 'Done' to finish setup.'''=Dokončete nastavení klepnutím na tlačítko „Done“ (Hotovo). +'''SmartThings Connection'''=Připojení SmartThings diff --git a/smartapps/smartthings/lifx-connect.src/i18n/da-DK.properties b/smartapps/smartthings/lifx-connect.src/i18n/da-DK.properties new file mode 100644 index 0000000..736c741 --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/da-DK.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Giver dig mulighed for at bruge LIFX-smartpærer sammen med SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Tryk for at indtaste LIFX-legitimationsoplysninger +'''Connect to LIFX'''=Forbind med LIFX +'''Tap here to connect your LIFX account'''=Tryk her for at forbinde din LIFX-konto +'''Connect to LIFX'''=Forbind med LIFX +'''Select your location'''=Vælg din placering +'''Select location ({{count}} found)'''=Vælg placering ({{count}} fundet) +'''Your LIFX Account is now connected to SmartThings!'''=Din LIFX-konto er nu forbundet med SmartThings! +'''Click 'Done' to finish setup.'''=Klik på “Done” (Udført) for at afslutte konfigurationen. +'''The connection could not be established!'''=Der kunne ikke oprettes forbindelse! +'''Click 'Done' to return to the menu.'''=Klik på “Done” (Udført) for at vende tilbage til menuen. +'''Your LIFX Account is already connected to SmartThings!'''=Din LIFX-konto er allerede forbundet med SmartThings! +'''Click 'Done' to finish setup.'''=Klik på “Done” (Udført) for at afslutte konfigurationen. +'''SmartThings Connection'''=SmartThings-forbindelse diff --git a/smartapps/smartthings/lifx-connect.src/i18n/de-DE.properties b/smartapps/smartthings/lifx-connect.src/i18n/de-DE.properties new file mode 100644 index 0000000..81ab993 --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/de-DE.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Ermöglicht die Verwendung intelligenter Glühbirnen von LIFX mit SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Tippen, um LIFX-Zugangsdaten einzugeben +'''Connect to LIFX'''=Mit LIFX verbinden +'''Tap here to connect your LIFX account'''=Hier tippen, um Ihr LIFX-Konto zu verbinden. +'''Connect to LIFX'''=Mit LIFX verbinden +'''Select your location'''=Ihren Standort auswählen +'''Select location ({{count}} found)'''=Standortauswahl ({{count}} gefunden) +'''Your LIFX Account is now connected to SmartThings!'''=Ihr LIFX-Konto ist jetzt mit SmartThings verbunden! +'''Click 'Done' to finish setup.'''=Klicken Sie auf „Done“ (OK), um die Einrichtung abzuschließen. +'''The connection could not be established!'''=Es konnte keine Verbindung hergestellt werden! +'''Click 'Done' to return to the menu.'''=Klicken Sie auf „Done“ (OK), um zum Menü zurückzukehren. +'''Your LIFX Account is already connected to SmartThings!'''=Ihr LIFX-Konto ist bereits mit SmartThings verbunden! +'''Click 'Done' to finish setup.'''=Klicken Sie auf „Done“ (OK), um die Einrichtung abzuschließen. +'''SmartThings Connection'''=SmartThings-Verbindung diff --git a/smartapps/smartthings/lifx-connect.src/i18n/el-GR.properties b/smartapps/smartthings/lifx-connect.src/i18n/el-GR.properties new file mode 100644 index 0000000..1e3ee15 --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/el-GR.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Σας επιτρέπει να χρησιμοποιείτε έξυπνους λαμπτήρες LIFX με το SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Πατήστε για να καταχωρήσετε διαπιστευτήρια LIFX +'''Connect to LIFX'''=Σύνδεση στο LIFX +'''Tap here to connect your LIFX account'''=Πατήστε εδώ για να συνδέσετε το λογαριασμό σας LIFX +'''Connect to LIFX'''=Σύνδεση στο LIFX +'''Select your location'''=Επιλέξτε την τοποθεσία σας +'''Select location ({{count}} found)'''=Επιλογή τοποθεσίας (βρέθηκαν {{count}}) +'''Your LIFX Account is now connected to SmartThings!'''=Ο λογαριασμός σας στο LIFX έχει τώρα συνδεθεί στο SmartThings! +'''Click 'Done' to finish setup.'''=Πατήστε "Done" (Τέλος) για να ολοκληρωθεί η ρύθμιση. +'''The connection could not be established!'''=Δεν ήταν δυνατή η δημιουργία σύνδεσης! +'''Click 'Done' to return to the menu.'''=Κάντε κλικ στο "Done" (Τέλος) για να επιστρέψετε στο μενού. +'''Your LIFX Account is already connected to SmartThings!'''=Ο λογαριασμός σας στο LIFX έχει ήδη συνδεθεί στο SmartThings! +'''Click 'Done' to finish setup.'''=Πατήστε "Done" (Τέλος) για να ολοκληρωθεί η ρύθμιση. +'''SmartThings Connection'''=Σύνδεση SmartThings diff --git a/smartapps/smartthings/lifx-connect.src/i18n/en-GB.properties b/smartapps/smartthings/lifx-connect.src/i18n/en-GB.properties new file mode 100644 index 0000000..1bdcdcc --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/en-GB.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Allows you to use LIFX smart light bulbs with SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Tap to enter LIFX credentials +'''Connect to LIFX'''=Connect to LIFX +'''Tap here to connect your LIFX account'''=Tap here to connect your LIFX account +'''Connect to LIFX'''=Connect to LIFX +'''Select your location'''=Select your location +'''Select location ({{count}} found)'''=Select location ({{count}} found) +'''Your LIFX Account is now connected to SmartThings!'''=Your LIFX Account is now connected to SmartThings! +'''Click 'Done' to finish setup.'''=Click ’Done’ to exit setup. +'''The connection could not be established!'''=The connection could not be established! +'''Click 'Done' to return to the menu.'''=Click ’Done’ to return to the menu. +'''Your LIFX Account is already connected to SmartThings!'''=Your LIFX Account is already connected to SmartThings! +'''Click 'Done' to finish setup.'''=Click ’Done’ to finish setup. +'''SmartThings Connection'''=SmartThings Connection diff --git a/smartapps/smartthings/lifx-connect.src/i18n/es-ES.properties b/smartapps/smartthings/lifx-connect.src/i18n/es-ES.properties new file mode 100644 index 0000000..0e14fc8 --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/es-ES.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Le permite utilizar bombillas de luz inteligente LIFX con SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Pulsar para introducir credenciales de LIFX +'''Connect to LIFX'''=Conectar a LIFX +'''Tap here to connect your LIFX account'''=Pulsar aquí para conectar la cuenta LIFX +'''Connect to LIFX'''=Conectar a LIFX +'''Select your location'''=Seleccionar ubicación +'''Select location ({{count}} found)'''=Seleccionar ubicación ({{count}} encontrado) +'''Your LIFX Account is now connected to SmartThings!'''=¡Su cuenta de LIFX ya está conectada a SmartThings! +'''Click 'Done' to finish setup.'''=Haga clic en “Done” (Hecho) para finalizar la configuración. +'''The connection could not be established!'''=¡No se ha podido establecer la conexión! +'''Click 'Done' to return to the menu.'''=Haga clic en “Done” (Hecho) para volver al menú. +'''Your LIFX Account is already connected to SmartThings!'''=¡Su cuenta de LIFX ya está conectada a SmartThings! +'''Click 'Done' to finish setup.'''=Haga clic en “Done” (Hecho) para finalizar la configuración. +'''SmartThings Connection'''=Conexión de SmartThings diff --git a/smartapps/smartthings/lifx-connect.src/i18n/es-US.properties b/smartapps/smartthings/lifx-connect.src/i18n/es-US.properties new file mode 100644 index 0000000..9e1960e --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/es-US.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Le permite usar las bombillas inteligentes LIFX con SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Pulse para introducir las credenciales de LIFX +'''Connect to LIFX'''=Conectar a LIFX +'''Tap here to connect your LIFX account'''=Pulse aquí para conectar su cuenta de LIFX +'''Connect to LIFX'''=Conectar a LIFX +'''Select your location'''=Seleccione su ubicación +'''Select location ({{count}} found)'''=Seleccionar ubicación (hay {{count}}) +'''Your LIFX Account is now connected to SmartThings!'''=¡Su cuenta de LIFX ahora está conectada a SmartThings! +'''Click 'Done' to finish setup.'''=Haga clic en 'Done' ('Listo') para finalizar la configuración. +'''The connection could not be established!'''=¡No fue posible establecer la conexión! +'''Click 'Done' to return to the menu.'''=Haga clic en 'Done' ('Listo') para volver al menú. +'''Your LIFX Account is already connected to SmartThings!'''=¡Su cuenta de LIFX ya está conectada a SmartThings! +'''Click 'Done' to finish setup.'''=Haga clic en 'Done' ('Listo') para finalizar la configuración. +'''SmartThings Connection'''=Conexión de SmartThings diff --git a/smartapps/smartthings/lifx-connect.src/i18n/et-EE.properties b/smartapps/smartthings/lifx-connect.src/i18n/et-EE.properties new file mode 100644 index 0000000..7403f58 --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/et-EE.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Võimaldab kasutada LIFXi nutikaid lambipirne teenusega SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Toksake, et sisestada teenuse LIFX volitused +'''Connect to LIFX'''=Loo ühendus teenusega LIFX +'''Tap here to connect your LIFX account'''=Toksake siia, et luua ühendus oma LIFXi kontoga +'''Connect to LIFX'''=Loo ühendus teenusega LIFX +'''Select your location'''=Valige oma asukoht +'''Select location ({{count}} found)'''=Valige asukoht ({{count}} found) +'''Your LIFX Account is now connected to SmartThings!'''=Teie LIFXi konto on nüüd ühendatud teenusega SmartThings! +'''Click 'Done' to finish setup.'''=Klõpsake valikut Valmis, et seadistamine lõpule viia. +'''The connection could not be established!'''=Ühenduse loomine nurjus! +'''Click 'Done' to return to the menu.'''=Klõpsake valikut Valmis, et naasta menüüsse. +'''Your LIFX Account is already connected to SmartThings!'''=Teie LIFXi konto on juba ühendatud teenusega SmartThings! +'''Click 'Done' to finish setup.'''=Klõpsake valikut Valmis, et seadistamine lõpule viia. +'''SmartThings Connection'''=Teenuse SmartThings ühendus diff --git a/smartapps/smartthings/lifx-connect.src/i18n/fi-FI.properties b/smartapps/smartthings/lifx-connect.src/i18n/fi-FI.properties new file mode 100644 index 0000000..d55d5c6 --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/fi-FI.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Mahdollistaa LIFX-älylamppujen käytön SmartThingsin kanssa. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Anna LIFX-tunnistetiedot +'''Connect to LIFX'''=Muodosta LIFX-yhteys +'''Tap here to connect your LIFX account'''=Napauta tätä, jos haluat muodostaa yhteyden LIFX-tiliisi +'''Connect to LIFX'''=Muodosta LIFX-yhteys +'''Select your location'''=Valitse sijaintisi +'''Select location ({{count}} found)'''=Valitse sijainti ({{count}} löydetty) +'''Your LIFX Account is now connected to SmartThings!'''=LIFX-tilisi on nyt yhdistetty SmartThingsiin! +'''Click 'Done' to finish setup.'''=Viimeistele asennus napsauttamalla Done (Valmis). +'''The connection could not be established!'''=Yhteyden muodostaminen epäonnistui! +'''Click 'Done' to return to the menu.'''=Palaa valikkoon napsauttamalla Done (Valmis). +'''Your LIFX Account is already connected to SmartThings!'''=LIFX-tilisi on jo yhdistetty SmartThingsiin! +'''Click 'Done' to finish setup.'''=Viimeistele asennus napsauttamalla Done (Valmis). +'''SmartThings Connection'''=SmartThings-yhteys diff --git a/smartapps/smartthings/lifx-connect.src/i18n/fr-CA.properties b/smartapps/smartthings/lifx-connect.src/i18n/fr-CA.properties new file mode 100644 index 0000000..c490995 --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/fr-CA.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Vous permet d'utiliser des ampoules intelligentes LIFX avec SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Appuyez pour saisir les informations d'identification LIFX +'''Connect to LIFX'''=Connexion à LIFX +'''Tap here to connect your LIFX account'''=Appuyez ici pour connecter votre compte LIFX +'''Connect to LIFX'''=Connexion à LIFX +'''Select your location'''=Sélection de votre zone géographique +'''Select location ({{count}} found)'''=Sélection d'une zone géographique ({{count}} trouvée(s)) +'''Your LIFX Account is now connected to SmartThings!'''=Votre compte LIFX est maintenant connecté à SmartThings ! +'''Click 'Done' to finish setup.'''=Cliquez sur Done (Terminé) pour terminer la configuration. +'''The connection could not be established!'''=La connexion n'a pas pu être établie ! +'''Click 'Done' to return to the menu.'''=Cliquez sur Done (Terminé) pour revenir au menu. +'''Your LIFX Account is already connected to SmartThings!'''=Votre compte LIFX est déjà connecté à SmartThings ! +'''Click 'Done' to finish setup.'''=Cliquez sur Done (Terminé) pour terminer la configuration. +'''SmartThings Connection'''=Connexion SmartThings diff --git a/smartapps/smartthings/lifx-connect.src/i18n/fr-FR.properties b/smartapps/smartthings/lifx-connect.src/i18n/fr-FR.properties new file mode 100644 index 0000000..c490995 --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/fr-FR.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Vous permet d'utiliser des ampoules intelligentes LIFX avec SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Appuyez pour saisir les informations d'identification LIFX +'''Connect to LIFX'''=Connexion à LIFX +'''Tap here to connect your LIFX account'''=Appuyez ici pour connecter votre compte LIFX +'''Connect to LIFX'''=Connexion à LIFX +'''Select your location'''=Sélection de votre zone géographique +'''Select location ({{count}} found)'''=Sélection d'une zone géographique ({{count}} trouvée(s)) +'''Your LIFX Account is now connected to SmartThings!'''=Votre compte LIFX est maintenant connecté à SmartThings ! +'''Click 'Done' to finish setup.'''=Cliquez sur Done (Terminé) pour terminer la configuration. +'''The connection could not be established!'''=La connexion n'a pas pu être établie ! +'''Click 'Done' to return to the menu.'''=Cliquez sur Done (Terminé) pour revenir au menu. +'''Your LIFX Account is already connected to SmartThings!'''=Votre compte LIFX est déjà connecté à SmartThings ! +'''Click 'Done' to finish setup.'''=Cliquez sur Done (Terminé) pour terminer la configuration. +'''SmartThings Connection'''=Connexion SmartThings diff --git a/smartapps/smartthings/lifx-connect.src/i18n/hr-HR.properties b/smartapps/smartthings/lifx-connect.src/i18n/hr-HR.properties new file mode 100644 index 0000000..515f96e --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/hr-HR.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Dopušta vam da upotrebljavate pametne žarulje LIFX s uslugom SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Dodirnite za unos podataka za prijavu za LIFX +'''Connect to LIFX'''=Povezivanje na LIFX +'''Tap here to connect your LIFX account'''=Dodirnite ovdje da biste povezali svoj račun za LIFX +'''Connect to LIFX'''=Povezivanje na LIFX +'''Select your location'''=Odaberite lokaciju +'''Select location ({{count}} found)'''=Odaberite lokaciju (pronađeno: {{count}}) +'''Your LIFX Account is now connected to SmartThings!'''=Račun za LIFX sada je povezan s uslugom SmartThings! +'''Click 'Done' to finish setup.'''=Kliknite „Done” (Gotovo) da biste dovršili postavljanje. +'''The connection could not be established!'''=Veza se nije uspostavila! +'''Click 'Done' to return to the menu.'''=Kliknite „Done” (Gotovo) za vraćanje na izbornik. +'''Your LIFX Account is already connected to SmartThings!'''=Račun za LIFX već je povezan s uslugom SmartThings! +'''Click 'Done' to finish setup.'''=Kliknite „Done” (Gotovo) da biste dovršili postavljanje. +'''SmartThings Connection'''=Veza za SmartThings diff --git a/smartapps/smartthings/lifx-connect.src/i18n/hu-HU.properties b/smartapps/smartthings/lifx-connect.src/i18n/hu-HU.properties new file mode 100644 index 0000000..df195d9 --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/hu-HU.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Lehetővé teszi a LIFX okoségők használatát a SmartThings rendszerrel. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Érintse meg a LIFX-hitelesítőadatok megadásához +'''Connect to LIFX'''=Csatlakozás a LIFX-hez +'''Tap here to connect your LIFX account'''=Érintse meg a LIFX-fiókjához való csatlakozáshoz +'''Connect to LIFX'''=Csatlakozás a LIFX-hez +'''Select your location'''=Hely kiválasztása +'''Select location ({{count}} found)'''=Hely kiválasztása ({{count}} találat) +'''Your LIFX Account is now connected to SmartThings!'''=Csatlakoztatta LIFX-fiókját a SmartThings rendszerhez! +'''Click 'Done' to finish setup.'''=A telepítés befejezéséhez kattintson a „Done” (Kész) gombra. +'''The connection could not be established!'''=Nem sikerült kapcsolatot létesíteni! +'''Click 'Done' to return to the menu.'''=A menühöz való visszatéréshez kattintson a „Done” (Kész) gombra. +'''Your LIFX Account is already connected to SmartThings!'''=LIFX-fiókja már csatlakozott a SmartThings rendszerhez! +'''Click 'Done' to finish setup.'''=A telepítés befejezéséhez kattintson a „Done” (Kész) gombra. +'''SmartThings Connection'''=SmartThings csatlakoztatása diff --git a/smartapps/smartthings/lifx-connect.src/i18n/it-IT.properties b/smartapps/smartthings/lifx-connect.src/i18n/it-IT.properties new file mode 100644 index 0000000..5319d68 --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/it-IT.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Vi consente di utilizzare le lampadine intelligenti LIFX con SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Toccate per inserire le credenziali LIFX +'''Connect to LIFX'''=Connetti a LIFX +'''Tap here to connect your LIFX account'''=Toccate qui per connettere l'account LIFX +'''Connect to LIFX'''=Connetti a LIFX +'''Select your location'''=Selezionate la posizione +'''Select location ({{count}} found)'''=Selezionate la posizione ({{count}} trovate) +'''Your LIFX Account is now connected to SmartThings!'''=L'account LIFX è adesso connesso a SmartThings. +'''Click 'Done' to finish setup.'''=Fate clic su “Done” (Fatto) per terminare la configurazione. +'''The connection could not be established!'''=Non è stato possibile stabilire la connessione. +'''Click 'Done' to return to the menu.'''=Fate clic su “Done” (Fatto) per tornare al menu. +'''Your LIFX Account is already connected to SmartThings!'''=L'account LIFX è già connesso a SmartThings. +'''Click 'Done' to finish setup.'''=Fate clic su “Done” (Fatto) per terminare la configurazione. +'''SmartThings Connection'''=Connessione a SmartThings diff --git a/smartapps/smartthings/lifx-connect.src/i18n/ko-KR.properties b/smartapps/smartthings/lifx-connect.src/i18n/ko-KR.properties new file mode 100644 index 0000000..cd65415 --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/ko-KR.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=LIFX 스마트 전구를 SmartThings에서 사용할 수 있습니다. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=LIFX 로그인 정보를 입력하려면 누르세요 +'''Connect to LIFX'''=LIFX 연결 +'''Tap here to connect your LIFX account'''=LIFX 계정을 연결하려면 여기를 누르세요 +'''Connect to LIFX'''=LIFX 연결 +'''Select your location'''=위치 선택 +'''Select location ({{count}} found)'''=위치 선택 ({{count}}개 찾음) +'''Your LIFX Account is now connected to SmartThings!'''=LIFX 계정이 SmartThings에 연결되었습니다! +'''Click 'Done' to finish setup.'''=설정을 완료하려면 [완료]를 클릭하세요. +'''The connection could not be established!'''=연결을 실행할 수 없습니다! +'''Click 'Done' to return to the menu.'''=메뉴로 돌아가려면 [완료]를 클릭하세요. +'''Your LIFX Account is already connected to SmartThings!'''=LIFX 계정이 SmartThings에 연결되어 있습니다! +'''Click 'Done' to finish setup.'''=설정을 완료하려면 [완료]를 클릭하세요. +'''SmartThings Connection'''=SmartThings 연결 diff --git a/smartapps/smartthings/lifx-connect.src/i18n/nl-NL.properties b/smartapps/smartthings/lifx-connect.src/i18n/nl-NL.properties new file mode 100644 index 0000000..d6ff791 --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/nl-NL.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Hiermee kunt u slimme lampen van LIFX gebruiken met SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Tik om LIFX-inloggegevens in te voeren +'''Connect to LIFX'''=Verbinden met LIFX +'''Tap here to connect your LIFX account'''=Tik hier om verbinding te maken met uw LIFX-account +'''Connect to LIFX'''=Verbinden met LIFX +'''Select your location'''=Selecteer uw locatie +'''Select location ({{count}} found)'''=Selecteer locatie ({{count}} gevonden) +'''Your LIFX Account is now connected to SmartThings!'''=Uw LIFX-account is nu verbonden met SmartThings. +'''Click 'Done' to finish setup.'''=Klik op Done (Gereed) om het instellen te voltooien. +'''The connection could not be established!'''=Er kan geen verbinding worden gemaakt. +'''Click 'Done' to return to the menu.'''=Klik op Done (Gereed) om terug te gaan naar het menu. +'''Your LIFX Account is already connected to SmartThings!'''=Uw LIFX-account is al verbonden met SmartThings. +'''Click 'Done' to finish setup.'''=Klik op Done (Gereed) om het instellen te voltooien. +'''SmartThings Connection'''=SmartThings-verbinding diff --git a/smartapps/smartthings/lifx-connect.src/i18n/no-NO.properties b/smartapps/smartthings/lifx-connect.src/i18n/no-NO.properties new file mode 100644 index 0000000..7a1459d --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/no-NO.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Gjør at du kan bruke LIFX-smartlyspærer med SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Trykk for å angi LIFX-informasjon +'''Connect to LIFX'''=Koble til LIFX +'''Tap here to connect your LIFX account'''=Trykk her for å koble til LIFX-kontoen din +'''Connect to LIFX'''=Koble til LIFX +'''Select your location'''=Velg plasseringen din +'''Select location ({{count}} found)'''=Velg plassering (fant {{count}}) +'''Your LIFX Account is now connected to SmartThings!'''=LIFX-kontoen din er nå koblet til SmartThings! +'''Click 'Done' to finish setup.'''=Klikk på Done (Ferdig) for å fullføre oppsettet. +'''The connection could not be established!'''=Kunne ikke opprette tilkoblingen! +'''Click 'Done' to return to the menu.'''=Klikk på Done (Ferdig) for å gå tilbake til menyen. +'''Your LIFX Account is already connected to SmartThings!'''=LIFX-kontoen din er allerede koblet til SmartThings! +'''Click 'Done' to finish setup.'''=Klikk på Done (Ferdig) for å fullføre oppsettet. +'''SmartThings Connection'''=SmartThings-tilkobling diff --git a/smartapps/smartthings/lifx-connect.src/i18n/pl-PL.properties b/smartapps/smartthings/lifx-connect.src/i18n/pl-PL.properties new file mode 100644 index 0000000..9078b31 --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/pl-PL.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Umożliwia użycie inteligentnych żarówek LIFX ze SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Dotknij, aby wprowadzić poświadczenia LIFX +'''Connect to LIFX'''=Połącz z LIFX +'''Tap here to connect your LIFX account'''=Dotknij tutaj, aby połączyć z kontem LIFX +'''Connect to LIFX'''=Połącz z LIFX +'''Select your location'''=Wybierz lokalizację +'''Select location ({{count}} found)'''=Wybierz lokalizację (znaleziono {{count}}) +'''Your LIFX Account is now connected to SmartThings!'''=Konto LIFX jest teraz połączone ze SmartThings. +'''Click 'Done' to finish setup.'''=Kliknij opcję „Done” (Gotowe), aby ukończyć instalację. +'''The connection could not be established!'''=Nie można ustanowić połączenia. +'''Click 'Done' to return to the menu.'''=Kliknij opcję „Done” (Gotowe), aby powrócić do menu. +'''Your LIFX Account is already connected to SmartThings!'''=Konto LIFX jest już połączone ze SmartThings. +'''Click 'Done' to finish setup.'''=Kliknij opcję „Done” (Gotowe), aby ukończyć instalację. +'''SmartThings Connection'''=Połączenie SmartThings diff --git a/smartapps/smartthings/lifx-connect.src/i18n/pt-BR.properties b/smartapps/smartthings/lifx-connect.src/i18n/pt-BR.properties new file mode 100644 index 0000000..ccb8010 --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/pt-BR.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Permite o uso de lâmpadas inteligentes LIFX com o SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Tocar para inserir as credenciais do LIFX +'''Connect to LIFX'''=Conectar ao LIFX +'''Tap here to connect your LIFX account'''=Tocar aqui para conectar sua conta LIFX +'''Connect to LIFX'''=Conectar ao LIFX +'''Select your location'''=Selecionar sua localização +'''Select location ({{count}} found)'''=Selecionar a localização ({{count}} encontrado) +'''Your LIFX Account is now connected to SmartThings!'''=Agora sua conta LIFX está conectada ao SmartThings! +'''Click 'Done' to finish setup.'''=Clique em 'Done' (Concluído) para concluir a configuração. +'''The connection could not be established!'''=Não foi possível estabelecer a conexão! +'''Click 'Done' to return to the menu.'''=Clique em 'Done' (Concluído) para retornar ao menu. +'''Your LIFX Account is already connected to SmartThings!'''=Sua conta LIFX já está conectada ao SmartThings! +'''Click 'Done' to finish setup.'''=Clique em 'Done' (Concluído) para concluir a configuração. +'''SmartThings Connection'''=Conexão com o SmartThings diff --git a/smartapps/smartthings/lifx-connect.src/i18n/pt-PT.properties b/smartapps/smartthings/lifx-connect.src/i18n/pt-PT.properties new file mode 100644 index 0000000..7248239 --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/pt-PT.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Permite a utilização de lâmpadas inteligentes LIFX com o SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Toque para introduzir as credenciais da LIFX +'''Connect to LIFX'''=Ligar à LIFX +'''Tap here to connect your LIFX account'''=Toque aqui para ligar a sua conta LIFX +'''Connect to LIFX'''=Ligar à LIFX +'''Select your location'''=Seleccionar a sua localização +'''Select location ({{count}} found)'''=Seleccionar a localização ({{count}} encontrado) +'''Your LIFX Account is now connected to SmartThings!'''=Agora, a sua Conta LIFX está ligada ao SmartThings! +'''Click 'Done' to finish setup.'''=Clique em "Done" (Concluir) para terminar a configuração. +'''The connection could not be established!'''=Não foi possível estabelecer a ligação! +'''Click 'Done' to return to the menu.'''=Clique em "Done" (Concluir) para regressar ao menu. +'''Your LIFX Account is already connected to SmartThings!'''=A sua conta LIFX já está ligada ao SmartThings! +'''Click 'Done' to finish setup.'''=Clique em "Done" (Concluir) para terminar a configuração. +'''SmartThings Connection'''=Ligação do SmartThings diff --git a/smartapps/smartthings/lifx-connect.src/i18n/ro-RO.properties b/smartapps/smartthings/lifx-connect.src/i18n/ro-RO.properties new file mode 100644 index 0000000..eccc6eb --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/ro-RO.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Permite utilizarea becurilor inteligente LIFX cu SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Atingeți pentru a introduce acreditările LIFX +'''Connect to LIFX'''=Conectare la LIFX +'''Tap here to connect your LIFX account'''=Atingeți aici pentru a vă conecta la contul LIFX +'''Connect to LIFX'''=Conectare la LIFX +'''Select your location'''=Selectați locația dvs. +'''Select location ({{count}} found)'''=Selectare locație ({{count}} găsite) +'''Your LIFX Account is now connected to SmartThings!'''=Contul dvs. LIFX este acum conectat la SmartThings! +'''Click 'Done' to finish setup.'''=Faceți clic pe „Done” (Efectuat) pentru a finaliza configurarea. +'''The connection could not be established!'''=Nu a putut fi stabilită conexiunea! +'''Click 'Done' to return to the menu.'''=Faceți clic pe „Done” (Efectuat) pentru a reveni la meniu. +'''Your LIFX Account is already connected to SmartThings!'''=Contul dvs. LIFX este deja conectat la SmartThings! +'''Click 'Done' to finish setup.'''=Faceți clic pe „Done” (Efectuat) pentru a finaliza configurarea. +'''SmartThings Connection'''=Conexiune SmartThings diff --git a/smartapps/smartthings/lifx-connect.src/i18n/ru-RU.properties b/smartapps/smartthings/lifx-connect.src/i18n/ru-RU.properties new file mode 100644 index 0000000..cbd7da1 --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/ru-RU.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Позволяет использовать умные электролампы LIFX со SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Коснитесь, чтобы ввести учетные данные LIFX +'''Connect to LIFX'''=Подключиться к LIFX +'''Tap here to connect your LIFX account'''=Коснитесь здесь, чтобы подключить свою учетную запись LIFX +'''Connect to LIFX'''=Подключиться к LIFX +'''Select your location'''=Выберите свое месторасположение +'''Select location ({{count}} found)'''=Выбор местоположения (найдено {{count}}) +'''Your LIFX Account is now connected to SmartThings!'''=Теперь ваша учетная запись LIFX подключена к SmartThings! +'''Click 'Done' to finish setup.'''=Для завершения настройки нажмите «Готово». +'''The connection could not be established!'''=Не удалось установить соединение! +'''Click 'Done' to return to the menu.'''=Чтобы вернуться в меню, нажмите «Готово». +'''Your LIFX Account is already connected to SmartThings!'''=Ваша учетная запись LIFX уже подключена к SmartThings! +'''Click 'Done' to finish setup.'''=Для завершения настройки нажмите «Готово». +'''SmartThings Connection'''=Подключение SmartThings diff --git a/smartapps/smartthings/lifx-connect.src/i18n/sk-SK.properties b/smartapps/smartthings/lifx-connect.src/i18n/sk-SK.properties new file mode 100644 index 0000000..2eec44c --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/sk-SK.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Umožňuje používať inteligentné žiarovky LIFX so systémom SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Ťuknutím zadajte poverenia pre LIFX +'''Connect to LIFX'''=Pripojenie k zariadeniu LIFX +'''Tap here to connect your LIFX account'''=Ťuknutím sem sa môžete pripojiť ku kontu LIFX +'''Connect to LIFX'''=Pripojenie k zariadeniu LIFX +'''Select your location'''=Vyberte umiestnenie +'''Select location ({{count}} found)'''=Vyberte umiestnenie (nájdené: {{count}}) +'''Your LIFX Account is now connected to SmartThings!'''=Vaše konto LIFX je teraz prepojené so systémom SmartThings. +'''Click 'Done' to finish setup.'''=Kliknutím na tlačidlo Done (Hotovo) dokončite inštaláciu. +'''The connection could not be established!'''=Nepodarilo sa nadviazať spojenie. +'''Click 'Done' to return to the menu.'''=Kliknutím na tlačidlo Done (Hotovo) sa vráťte do menu. +'''Your LIFX Account is already connected to SmartThings!'''=Vaše konto LIFX je už prepojené so systémom SmartThings. +'''Click 'Done' to finish setup.'''=Kliknutím na tlačidlo Done (Hotovo) dokončite inštaláciu. +'''SmartThings Connection'''=Pripojenie k zariadeniu SmartThings diff --git a/smartapps/smartthings/lifx-connect.src/i18n/sl-SI.properties b/smartapps/smartthings/lifx-connect.src/i18n/sl-SI.properties new file mode 100644 index 0000000..d298313 --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/sl-SI.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Omogoča uporabo pametnih žarnic LIFX s storitvijo SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Pritisnite za vnos poverilnic LIFX +'''Connect to LIFX'''=Povezava z LIFX +'''Tap here to connect your LIFX account'''=Pritisnite tukaj, da povežete račun LIFX +'''Connect to LIFX'''=Povezava z LIFX +'''Select your location'''=Izberite svojo lokacijo +'''Select location ({{count}} found)'''=Izberite lokacijo (št. najdenih: {{count}}) +'''Your LIFX Account is now connected to SmartThings!'''=Vaš račun LIFX je zdaj povezan s storitvijo SmartThings! +'''Click 'Done' to finish setup.'''=Kliknite »Done« (Končano), da zaključite nastavitev. +'''The connection could not be established!'''=Povezave ni bilo mogoče vzpostaviti! +'''Click 'Done' to return to the menu.'''=Kliknite »Done« (Končano), da se vrnete v meni. +'''Your LIFX Account is already connected to SmartThings!'''=Račun LIFX je že povezan s storitvijo SmartThings! +'''Click 'Done' to finish setup.'''=Kliknite »Done« (Končano), da zaključite nastavitev. +'''SmartThings Connection'''=Povezava SmartThings diff --git a/smartapps/smartthings/lifx-connect.src/i18n/sq-AL.properties b/smartapps/smartthings/lifx-connect.src/i18n/sq-AL.properties new file mode 100644 index 0000000..7a313ec --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/sq-AL.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Të lejon të përdorësh llamba inteligjente LIFX me SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Trokit për të futur kredencialet LIFX +'''Connect to LIFX'''=Lidhu me LIFX +'''Tap here to connect your LIFX account'''=Trokit këtu për të lidhur llogarinë LIFX +'''Connect to LIFX'''=Lidhu me LIFX +'''Select your location'''=Përzgjidh vendndodhjen tënde +'''Select location ({{count}} found)'''=Përzgjidh vendndodhjen (u gjet {{count}}) +'''Your LIFX Account is now connected to SmartThings!'''=Llogaria jote LIFX tani është lidhur me SmartThings! +'''Click 'Done' to finish setup.'''=Kliko mbi ‘Done’ (U krye) për ta mbaruar konfigurimin. +'''The connection could not be established!'''=Lidhja nuk u vendos dot! +'''Click 'Done' to return to the menu.'''=Kliko mbi ‘Done’ (U krye) për t’u kthyer në meny. +'''Your LIFX Account is already connected to SmartThings!'''=Llogaria jote LIFX tashmë është lidhur me SmartThings! +'''Click 'Done' to finish setup.'''=Kliko mbi ‘Done’ (U krye) për ta mbaruar konfigurimin. +'''SmartThings Connection'''=Lidhja SmartThings diff --git a/smartapps/smartthings/lifx-connect.src/i18n/sr-RS.properties b/smartapps/smartthings/lifx-connect.src/i18n/sr-RS.properties new file mode 100644 index 0000000..3e3b477 --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/sr-RS.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Dozvoljava vam da koristite LIFX pametne sijalice sa aplikacijom SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Kucnite za unos LIFX akreditiva +'''Connect to LIFX'''=Povežite se na LIFX +'''Tap here to connect your LIFX account'''=Kucnite ovde da biste se povezali na svoj LIFX nalog +'''Connect to LIFX'''=Povežite se na LIFX +'''Select your location'''=Izaberite lokaciju na kojoj se nalazite +'''Select location ({{count}} found)'''=Izaberite lokaciju ({{count}} pronađeno) +'''Your LIFX Account is now connected to SmartThings!'''=Vaš LIFX nalog je sada povezan na SmartThings! +'''Click 'Done' to finish setup.'''=Kliknite na „Done” (Gotovo) za kraj konfiguracije. +'''The connection could not be established!'''=Veza nije uspostavljena! +'''Click 'Done' to return to the menu.'''=Kliknite na „Done” (Gotovo) da biste se vratili na meni. +'''Your LIFX Account is already connected to SmartThings!'''=Vaš LIFX nalog je već povezan na SmartThings! +'''Click 'Done' to finish setup.'''=Kliknite na „Done” (Gotovo) za kraj konfiguracije. +'''SmartThings Connection'''=SmartThings veza diff --git a/smartapps/smartthings/lifx-connect.src/i18n/sv-SE.properties b/smartapps/smartthings/lifx-connect.src/i18n/sv-SE.properties new file mode 100644 index 0000000..434d302 --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/sv-SE.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=Gör att du kan använda de smarta LIFX-lamporna med SmartThings. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=Tryck för att ange LIFX-inloggningsuppgifter +'''Connect to LIFX'''=Anslut till LIFX +'''Tap here to connect your LIFX account'''=Tryck här för att avsluta ditt LIFX-konto +'''Connect to LIFX'''=Anslut till LIFX +'''Select your location'''=Välj din plats +'''Select location ({{count}} found)'''=Välj plats ({{count}} hittades) +'''Your LIFX Account is now connected to SmartThings!'''=Ditt LIFX-konto är nu anslutet till SmartThings! +'''Click 'Done' to finish setup.'''=Klicka på Done (Klart) för att slutföra konfigurationen. +'''The connection could not be established!'''=Det gick inte att upprätta anslutningen! +'''Click 'Done' to return to the menu.'''=Klicka på Done (Klart) för att återgå till menyn. +'''Your LIFX Account is already connected to SmartThings!'''=Ditt LIFX-konto är redan anslutet till SmartThings! +'''Click 'Done' to finish setup.'''=Klicka på Done (Klart) för att slutföra konfigurationen. +'''SmartThings Connection'''=SmartThings-anslutning diff --git a/smartapps/smartthings/lifx-connect.src/i18n/th-TH.properties b/smartapps/smartthings/lifx-connect.src/i18n/th-TH.properties new file mode 100644 index 0000000..2bccbb8 --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/th-TH.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=ทำให้คุณสามารถใช้หลอดไฟอัจฉริยะ LIFX กับ SmartThings ได้ +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=แตะเพื่อใส่ข้อมูลยืนยันตัวตน LIFX +'''Connect to LIFX'''=เชื่อมต่อกับ LIFX +'''Tap here to connect your LIFX account'''=แตะที่นี่เพื่อเชื่อมต่อบัญชีผู้ใช้ LIFX ของคุณ +'''Connect to LIFX'''=เชื่อมต่อกับ LIFX +'''Select your location'''=เลือกตำแหน่งของคุณ +'''Select location ({{count}} found)'''=เลือกตำแหน่ง ({{count}} found) +'''Your LIFX Account is now connected to SmartThings!'''=ตอนนี้บัญชีผู้ใช้ LIFX ของคุณเชื่อมต่อกับ SmartThings แล้ว! +'''Click 'Done' to finish setup.'''=คลิก 'เสร็จสิ้น' เพื่อทำการตั้งค่าให้เสร็จสิ้น +'''The connection could not be established!'''=ไม่สามารถสร้างการเชื่อมต่อได้! +'''Click 'Done' to return to the menu.'''=คลิก 'เสร็จสิ้น' เพื่อกลับไปยังเมนู +'''Your LIFX Account is already connected to SmartThings!'''=บัญชีผู้ใช้ LIFX ของคุณเชื่อมต่อกับ SmartThings อยู่แล้ว! +'''Click 'Done' to finish setup.'''=คลิก 'เสร็จสิ้น' เพื่อทำการตั้งค่าให้เสร็จสิ้น +'''SmartThings Connection'''=การเชื่อมต่อ SmartThings diff --git a/smartapps/smartthings/lifx-connect.src/i18n/tr-TR.properties b/smartapps/smartthings/lifx-connect.src/i18n/tr-TR.properties new file mode 100644 index 0000000..5e6980c --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/tr-TR.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=LIFX akıllı ampulleri SmartThings ile birlikte kullanabilmenizi sağlar. +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=LIFX kimlik bilgilerini girmek için dokunun +'''Connect to LIFX'''=LIFX'e bağlan +'''Tap here to connect your LIFX account'''=LIFX hesabınıza bağlanmak için buraya dokunun +'''Connect to LIFX'''=LIFX'e bağlan +'''Select your location'''=Konumunuzu seçin +'''Select location ({{count}} found)'''=Konum seçin ({{count}} bulundu) +'''Your LIFX Account is now connected to SmartThings!'''=LIFX Hesabınız artık SmartThings'e bağlandı! +'''Click 'Done' to finish setup.'''=Kurulumu bitirmek için 'Bitti' öğesine tıklayın. +'''The connection could not be established!'''=Bağlantı kurulamadı! +'''Click 'Done' to return to the menu.'''=Menüye dönmek için 'Bitti' öğesine tıklayın. +'''Your LIFX Account is already connected to SmartThings!'''=LIFX Hesabınız zaten SmartThings'e bağlı! +'''Click 'Done' to finish setup.'''=Kurulumu bitirmek için 'Bitti' öğesine tıklayın. +'''SmartThings Connection'''=SmartThings Bağlantısı diff --git a/smartapps/smartthings/lifx-connect.src/i18n/zh-CN.properties b/smartapps/smartthings/lifx-connect.src/i18n/zh-CN.properties new file mode 100644 index 0000000..1faaee3 --- /dev/null +++ b/smartapps/smartthings/lifx-connect.src/i18n/zh-CN.properties @@ -0,0 +1,15 @@ +'''Allows you to use LIFX smart light bulbs with SmartThings.'''=允许您将 LIFX 智能灯泡与 SmartThings 一起使用。 +'''LIFX'''=LIFX +'''Tap to enter LIFX credentials'''=点击以输入 LIFX 凭据 +'''Connect to LIFX'''=连接至 LIFX +'''Tap here to connect your LIFX account'''=点击此处连接 LIFX 帐户 +'''Connect to LIFX'''=连接至 LIFX +'''Select your location'''=选择您的位置 +'''Select location ({{count}} found)'''=选择位置 (发现 {{count}} 个) +'''Your LIFX Account is now connected to SmartThings!'''=LIFX 帐户现在已连接至 SmartThings! +'''Click 'Done' to finish setup.'''=单击“完成”以完成设置。 +'''The connection could not be established!'''=无法建立连接! +'''Click 'Done' to return to the menu.'''=单击“完成”返回菜单。 +'''Your LIFX Account is already connected to SmartThings!'''=LIFX 帐户现在已连接至 SmartThings! +'''Click 'Done' to finish setup.'''=单击“完成”以完成设置。 +'''SmartThings Connection'''=SmartThings 连接 diff --git a/smartapps/smartthings/lifx-connect.src/lifx-connect.groovy b/smartapps/smartthings/lifx-connect.src/lifx-connect.groovy index 7a4afe7..974561e 100644 --- a/smartapps/smartthings/lifx-connect.src/lifx-connect.groovy +++ b/smartapps/smartthings/lifx-connect.src/lifx-connect.groovy @@ -4,6 +4,8 @@ * Copyright 2015 LIFX * */ +include 'localization' + definition( name: "LIFX (Connect)", namespace: "smartthings", @@ -66,7 +68,7 @@ def authPage() { return dynamicPage(name:"Credentials", title:"", nextPage:"", install:true, uninstall: true) { section("Select your location") { - input "selectedLocationId", "enum", required:true, title:"Select location (${count} found)", multiple:false, options:options, submitOnChange: true + input "selectedLocationId", "enum", required:true, title:"Select location ({{count}} found)", messageArgs: [count: count], multiple:false, options:options, submitOnChange: true } } } @@ -346,7 +348,7 @@ def devicesList(selector = '') { if (resp.status == 200) { return resp.data } else { - log.error("Non-200 from device list call. ${resp.status} ${resp.data}") + log.debug("No response from device list call. ${resp.status} ${resp.data}") return [] } } @@ -418,9 +420,15 @@ def updateDevices() { } getChildDevices().findAll { !selectors.contains("${it.deviceNetworkId}") }.each { log.info("Deleting ${it.deviceNetworkId}") - state.devices[it.deviceNetworkId] = null - deleteChildDevice(it.deviceNetworkId) + if (state.devices[it.deviceNetworkId]) + state.devices[it.deviceNetworkId] = null + // The reason the implementation is trying to delete this bulb is because it is not longer connected to the LIFX location. + // Adding "try" will prevent this exception from happening. + // Ideally device health would show to the user that the device is not longer accessible so that the user can either force delete it or remove it from the SmartApp. + try { + deleteChildDevice(it.deviceNetworkId) + } catch (Exception e) { + log.debug("Can't remove this device because it's being used by an SmartApp") + } } } - -