mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-03-18 05:10:52 +00:00
Compare commits
49 Commits
MSA-1435-1
...
PROD_2016.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d65150bf7 | ||
|
|
99d6e9f668 | ||
|
|
a35f271a8e | ||
|
|
fd4969981f | ||
|
|
79b90d741f | ||
|
|
6009bc52ab | ||
|
|
33a8fe108e | ||
|
|
910694f1d1 | ||
|
|
fa9ebed998 | ||
|
|
df6646103a | ||
|
|
014affe1ea | ||
|
|
53fc948b00 | ||
|
|
f389e925d2 | ||
|
|
ef47ec9393 | ||
|
|
62d800e99a | ||
|
|
a79c9c1ade | ||
|
|
4505ca85b2 | ||
|
|
3c0c050b3a | ||
|
|
2cd915ba77 | ||
|
|
4866ecd204 | ||
|
|
f0071aad6d | ||
|
|
0d4a00ae2b | ||
|
|
90384d0852 | ||
|
|
47183ebbff | ||
|
|
d68f70b3dd | ||
|
|
e1b1479cfc | ||
|
|
16e4954f10 | ||
|
|
a1b375c929 | ||
|
|
929f8e1a44 | ||
|
|
4f97d1a3ef | ||
|
|
255185ee8c | ||
|
|
ad50582e92 | ||
|
|
6de6704502 | ||
|
|
a5bc475cc1 | ||
|
|
4fd5cc5d70 | ||
|
|
236c37290e | ||
|
|
7beb2e3905 | ||
|
|
d17bc1869f | ||
|
|
534118a47a | ||
|
|
7bfa0304af | ||
|
|
842f39e9ff | ||
|
|
dd308f6d8f | ||
|
|
1a72158a9a | ||
|
|
94ab309335 | ||
|
|
f2d635ab44 | ||
|
|
a7cd9e072b | ||
|
|
b5843acc38 | ||
|
|
4e5d1f6ad0 | ||
|
|
ef29820fa1 |
@@ -64,8 +64,10 @@ metadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
standardTile("switch", "device.switch", width: 1, height: 1, canChangeIcon: true) {
|
standardTile("switch", "device.switch", width: 1, height: 1, canChangeIcon: true) {
|
||||||
state "off", label: '${name}', action: "switch.on", icon: "st.Electronics.electronics16", backgroundColor: "#ffffff"
|
state "on", label: '${name}', action: "switch.off", icon: "st.Electronics.electronics16", backgroundColor: "#79b821", nextState:"turningOff"
|
||||||
state "on", label: '${name}', action: "switch.off", icon: "st.Electronics.electronics16", backgroundColor: "#79b821"
|
state "turningOff", label:'TURNING OFF', icon:"st.Electronics.electronics16", backgroundColor:"#ffffff"
|
||||||
|
state "off", label: '${name}', action: "switch.on", icon: "st.Electronics.electronics16", backgroundColor: "#ffffff", nextState:"turningOn"
|
||||||
|
state "turningOn", label:'TURNING ON', icon:"st.Electronics.electronics16", backgroundColor:"#79b821"
|
||||||
}
|
}
|
||||||
valueTile("1", "device.station1", decoration: "flat", canChangeIcon: false) {
|
valueTile("1", "device.station1", decoration: "flat", canChangeIcon: false) {
|
||||||
state "station1", label:'${currentValue}', action:"preset1"
|
state "station1", label:'${currentValue}', action:"preset1"
|
||||||
@@ -747,8 +749,16 @@ def cb_boseSetInput(xml, input) {
|
|||||||
*/
|
*/
|
||||||
def boseSetPowerState(boolean enable) {
|
def boseSetPowerState(boolean enable) {
|
||||||
log.info "boseSetPowerState(${enable})"
|
log.info "boseSetPowerState(${enable})"
|
||||||
queueCallback('nowPlaying', "cb_boseSetPowerState", enable ? "POWERON" : "POWEROFF")
|
// Fix to get faster update of power status back from speaker after sending on/off
|
||||||
return boseRefreshNowPlaying()
|
// Instead of queuing the command to be sent after the refresh send it directly via sendHubCommand
|
||||||
|
// Note: This is a temporary hack that should be replaced by a re-design of the
|
||||||
|
// DTH to use sendHubCommand for all commands
|
||||||
|
sendHubCommand(bosePOST("/key", "<key state=\"press\" sender=\"Gabbo\">POWER</key>"))
|
||||||
|
sendHubCommand(bosePOST("/key", "<key state=\"release\" sender=\"Gabbo\">POWER</key>"))
|
||||||
|
sendHubCommand(boseGET("/now_playing"))
|
||||||
|
if (enable) {
|
||||||
|
queueCallback('nowPlaying', "cb_boseConfirmPowerOn", 5)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -787,10 +797,11 @@ def cb_boseSetPowerState(xml, state) {
|
|||||||
*/
|
*/
|
||||||
def cb_boseConfirmPowerOn(xml, tries) {
|
def cb_boseConfirmPowerOn(xml, tries) {
|
||||||
def result = []
|
def result = []
|
||||||
log.warn "boseConfirmPowerOn() attempt #" + tries
|
def attempt = tries as Integer
|
||||||
if (xml.attributes()['source'] == "STANDBY" && tries > 0) {
|
log.warn "boseConfirmPowerOn() attempt #$attempt"
|
||||||
|
if (xml.attributes()['source'] == "STANDBY" && attempt > 0) {
|
||||||
result << boseRefreshNowPlaying()
|
result << boseRefreshNowPlaying()
|
||||||
queueCallback('nowPlaying', "cb_boseConfirmPowerOn", tries-1)
|
queueCallback('nowPlaying', "cb_boseConfirmPowerOn", attempt-1)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ metadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
standardTile("reset", "device.reset", height: 2, width: 2, inactiveLabel: false, decoration: "flat") {
|
standardTile("reset", "device.reset", height: 2, width: 2, inactiveLabel: false, decoration: "flat") {
|
||||||
state "default", label:"Reset Color", action:"reset", icon:"st.lights.philips.hue-single"
|
state "default", label:"Reset To White", action:"reset", icon:"st.lights.philips.hue-single"
|
||||||
}
|
}
|
||||||
|
|
||||||
standardTile("refresh", "device.refresh", height: 2, width: 2, inactiveLabel: false, decoration: "flat") {
|
standardTile("refresh", "device.refresh", height: 2, width: 2, inactiveLabel: false, decoration: "flat") {
|
||||||
@@ -51,7 +51,7 @@ metadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
main(["rich-control"])
|
main(["rich-control"])
|
||||||
details(["rich-control", "colorTempSliderControl", "colorTemp", "reset", "refresh"])
|
details(["rich-control", "reset", "refresh"])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,118 +75,78 @@ def parse(description) {
|
|||||||
// handle commands
|
// handle commands
|
||||||
void on() {
|
void on() {
|
||||||
log.trace parent.on(this)
|
log.trace parent.on(this)
|
||||||
sendEvent(name: "switch", value: "on")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void off() {
|
void off() {
|
||||||
log.trace parent.off(this)
|
log.trace parent.off(this)
|
||||||
sendEvent(name: "switch", value: "off")
|
|
||||||
}
|
|
||||||
|
|
||||||
void nextLevel() {
|
|
||||||
def level = device.latestValue("level") as Integer ?: 0
|
|
||||||
if (level <= 100) {
|
|
||||||
level = Math.min(25 * (Math.round(level / 25) + 1), 100) as Integer
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
level = 25
|
|
||||||
}
|
|
||||||
setLevel(level)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLevel(percent) {
|
void setLevel(percent) {
|
||||||
log.debug "Executing 'setLevel'"
|
log.debug "Executing 'setLevel'"
|
||||||
if (verifyPercent(percent)) {
|
if (verifyPercent(percent)) {
|
||||||
parent.setLevel(this, percent)
|
log.trace parent.setLevel(this, percent)
|
||||||
sendEvent(name: "level", value: percent, descriptionText: "Level has changed to ${percent}%")
|
|
||||||
sendEvent(name: "switch", value: "on")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSaturation(percent) {
|
void setSaturation(percent) {
|
||||||
log.debug "Executing 'setSaturation'"
|
log.debug "Executing 'setSaturation'"
|
||||||
if (verifyPercent(percent)) {
|
if (verifyPercent(percent)) {
|
||||||
parent.setSaturation(this, percent)
|
log.trace parent.setSaturation(this, percent)
|
||||||
sendEvent(name: "saturation", value: percent, displayed: false)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setHue(percent) {
|
void setHue(percent) {
|
||||||
log.debug "Executing 'setHue'"
|
log.debug "Executing 'setHue'"
|
||||||
if (verifyPercent(percent)) {
|
if (verifyPercent(percent)) {
|
||||||
parent.setHue(this, percent)
|
log.trace parent.setHue(this, percent)
|
||||||
sendEvent(name: "hue", value: percent, displayed: false)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setColor(value) {
|
void setColor(value) {
|
||||||
log.debug "setColor: ${value}, $this"
|
|
||||||
def events = []
|
def events = []
|
||||||
def validValues = [:]
|
def validValues = [:]
|
||||||
|
|
||||||
if (verifyPercent(value.hue)) {
|
if (verifyPercent(value.hue)) {
|
||||||
events << createEvent(name: "hue", value: value.hue, displayed: false)
|
|
||||||
validValues.hue = value.hue
|
validValues.hue = value.hue
|
||||||
}
|
}
|
||||||
if (verifyPercent(value.saturation)) {
|
if (verifyPercent(value.saturation)) {
|
||||||
events << createEvent(name: "saturation", value: value.saturation, displayed: false)
|
|
||||||
validValues.saturation = value.saturation
|
validValues.saturation = value.saturation
|
||||||
}
|
}
|
||||||
if (value.hex != null) {
|
if (value.hex != null) {
|
||||||
if (value.hex ==~ /^\#([A-Fa-f0-9]){6}$/) {
|
if (value.hex ==~ /^\#([A-Fa-f0-9]){6}$/) {
|
||||||
events << createEvent(name: "color", value: value.hex)
|
|
||||||
validValues.hex = value.hex
|
validValues.hex = value.hex
|
||||||
} else {
|
} else {
|
||||||
log.warn "$value.hex is not a valid color"
|
log.warn "$value.hex is not a valid color"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (verifyPercent(value.level)) {
|
if (verifyPercent(value.level)) {
|
||||||
events << createEvent(name: "level", value: value.level, descriptionText: "Level has changed to ${value.level}%")
|
|
||||||
validValues.level = value.level
|
validValues.level = value.level
|
||||||
}
|
}
|
||||||
if (value.switch == "off" || (value.level != null && value.level <= 0)) {
|
if (value.switch == "off" || (value.level != null && value.level <= 0)) {
|
||||||
events << createEvent(name: "switch", value: "off")
|
|
||||||
validValues.switch = "off"
|
validValues.switch = "off"
|
||||||
} else {
|
} else {
|
||||||
events << createEvent(name: "switch", value: "on")
|
|
||||||
validValues.switch = "on"
|
validValues.switch = "on"
|
||||||
}
|
}
|
||||||
if (!events.isEmpty()) {
|
if (!validValues.isEmpty()) {
|
||||||
parent.setColor(this, validValues)
|
log.trace parent.setColor(this, validValues)
|
||||||
}
|
|
||||||
events.each {
|
|
||||||
sendEvent(it)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
log.debug "Executing 'reset'"
|
log.debug "Executing 'reset'"
|
||||||
def value = [level:100, saturation:56, hue:23]
|
def value = [hue:20, saturation:2]
|
||||||
setAdjustedColor(value)
|
setAdjustedColor(value)
|
||||||
parent.poll()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setAdjustedColor(value) {
|
void setAdjustedColor(value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
log.trace "setAdjustedColor: ${value}"
|
log.trace "setAdjustedColor: ${value}"
|
||||||
def adjusted = value + [:]
|
def adjusted = value + [:]
|
||||||
adjusted.hue = adjustOutgoingHue(value.hue)
|
|
||||||
// Needed because color picker always sends 100
|
// Needed because color picker always sends 100
|
||||||
adjusted.level = null
|
adjusted.level = null
|
||||||
setColor(adjusted)
|
setColor(adjusted)
|
||||||
} else {
|
} else {
|
||||||
log.warn "Invalid color input"
|
log.warn "Invalid color input $value"
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setColorTemperature(value) {
|
|
||||||
if (value) {
|
|
||||||
log.trace "setColorTemperature: ${value}k"
|
|
||||||
parent.setColorTemperature(this, value)
|
|
||||||
sendEvent(name: "colorTemperature", value: value)
|
|
||||||
sendEvent(name: "switch", value: "on")
|
|
||||||
} else {
|
|
||||||
log.warn "Invalid color temperature"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,22 +155,6 @@ void refresh() {
|
|||||||
parent.manualRefresh()
|
parent.manualRefresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
def adjustOutgoingHue(percent) {
|
|
||||||
def adjusted = percent
|
|
||||||
if (percent > 31) {
|
|
||||||
if (percent < 63.0) {
|
|
||||||
adjusted = percent + (7 * (percent -30 ) / 32)
|
|
||||||
}
|
|
||||||
else if (percent < 73.0) {
|
|
||||||
adjusted = 69 + (5 * (percent - 62) / 10)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
adjusted = percent + (2 * (100 - percent) / 28)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.info "percent: $percent, adjusted: $adjusted"
|
|
||||||
adjusted
|
|
||||||
}
|
|
||||||
|
|
||||||
def verifyPercent(percent) {
|
def verifyPercent(percent) {
|
||||||
if (percent == null)
|
if (percent == null)
|
||||||
|
|||||||
@@ -7,8 +7,13 @@
|
|||||||
metadata {
|
metadata {
|
||||||
// Automatically generated. Make future change here.
|
// Automatically generated. Make future change here.
|
||||||
definition (name: "Hue Bridge", namespace: "smartthings", author: "SmartThings") {
|
definition (name: "Hue Bridge", namespace: "smartthings", author: "SmartThings") {
|
||||||
attribute "serialNumber", "string"
|
|
||||||
attribute "networkAddress", "string"
|
attribute "networkAddress", "string"
|
||||||
|
// Used to indicate if bridge is reachable or not, i.e. is the bridge connected to the network
|
||||||
|
// Possible values "Online" or "Offline"
|
||||||
|
attribute "status", "string"
|
||||||
|
// Id is the number on the back of the hub, Hue uses last six digits of Mac address
|
||||||
|
// This is also used in the Hue application as ID
|
||||||
|
attribute "idNumber", "string"
|
||||||
}
|
}
|
||||||
|
|
||||||
simulator {
|
simulator {
|
||||||
@@ -17,22 +22,23 @@ metadata {
|
|||||||
|
|
||||||
tiles(scale: 2) {
|
tiles(scale: 2) {
|
||||||
multiAttributeTile(name:"rich-control"){
|
multiAttributeTile(name:"rich-control"){
|
||||||
tileAttribute ("", key: "PRIMARY_CONTROL") {
|
tileAttribute ("device.status", key: "PRIMARY_CONTROL") {
|
||||||
attributeState "default", label: "Hue Bridge", action: "", icon: "st.Lighting.light99-hue", backgroundColor: "#F3C200"
|
attributeState "Offline", label: '${currentValue}', action: "", icon: "st.Lighting.light99-hue", backgroundColor: "#ffffff"
|
||||||
|
attributeState "Online", label: '${currentValue}', action: "", icon: "st.Lighting.light99-hue", backgroundColor: "#79b821"
|
||||||
}
|
}
|
||||||
tileAttribute ("serialNumber", key: "SECONDARY_CONTROL") {
|
|
||||||
attributeState "default", label:'SN: ${currentValue}'
|
|
||||||
}
|
}
|
||||||
|
valueTile("doNotRemove", "v", decoration: "flat", height: 2, width: 6, inactiveLabel: false) {
|
||||||
|
state "default", label:'Do not remove'
|
||||||
}
|
}
|
||||||
valueTile("serialNumber", "device.serialNumber", decoration: "flat", height: 1, width: 2, inactiveLabel: false) {
|
valueTile("idNumber", "device.idNumber", decoration: "flat", height: 2, width: 6, inactiveLabel: false) {
|
||||||
state "default", label:'SN: ${currentValue}'
|
state "default", label:'ID: ${currentValue}'
|
||||||
}
|
}
|
||||||
valueTile("networkAddress", "device.networkAddress", decoration: "flat", height: 2, width: 4, inactiveLabel: false) {
|
valueTile("networkAddress", "device.networkAddress", decoration: "flat", height: 2, width: 6, inactiveLabel: false) {
|
||||||
state "default", label:'${currentValue}', height: 1, width: 2, inactiveLabel: false
|
state "default", label:'IP: ${currentValue}'
|
||||||
}
|
}
|
||||||
|
|
||||||
main (["rich-control"])
|
main (["rich-control"])
|
||||||
details(["rich-control", "networkAddress"])
|
details(["rich-control", "idNumber", "networkAddress", "doNotRemove"])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,16 +43,16 @@ metadata {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2000..6500)") {
|
controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2000..6500)") {
|
||||||
state "colorTemperature", action:"color temperature.setColorTemperature"
|
state "colorTemperature", action:"color temperature.setColorTemperature"
|
||||||
}
|
}
|
||||||
|
|
||||||
valueTile("colorTemp", "device.colorTemperature", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
|
valueTile("colorTemp", "device.colorTemperature", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
|
||||||
state "colorTemperature", label: '${currentValue} K'
|
state "colorTemperature", label: 'WHITES'
|
||||||
}
|
}
|
||||||
|
|
||||||
standardTile("reset", "device.reset", height: 2, width: 2, inactiveLabel: false, decoration: "flat") {
|
standardTile("reset", "device.reset", height: 2, width: 2, inactiveLabel: false, decoration: "flat") {
|
||||||
state "default", label:"Reset Color", action:"reset", icon:"st.lights.philips.hue-single"
|
state "default", label:"Reset To White", action:"reset", icon:"st.lights.philips.hue-single"
|
||||||
}
|
}
|
||||||
|
|
||||||
standardTile("refresh", "device.refresh", height: 2, width: 2, inactiveLabel: false, decoration: "flat") {
|
standardTile("refresh", "device.refresh", height: 2, width: 2, inactiveLabel: false, decoration: "flat") {
|
||||||
@@ -84,118 +84,86 @@ def parse(description) {
|
|||||||
// handle commands
|
// handle commands
|
||||||
void on() {
|
void on() {
|
||||||
log.trace parent.on(this)
|
log.trace parent.on(this)
|
||||||
sendEvent(name: "switch", value: "on")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void off() {
|
void off() {
|
||||||
log.trace parent.off(this)
|
log.trace parent.off(this)
|
||||||
sendEvent(name: "switch", value: "off")
|
|
||||||
}
|
|
||||||
|
|
||||||
void nextLevel() {
|
|
||||||
def level = device.latestValue("level") as Integer ?: 0
|
|
||||||
if (level <= 100) {
|
|
||||||
level = Math.min(25 * (Math.round(level / 25) + 1), 100) as Integer
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
level = 25
|
|
||||||
}
|
|
||||||
setLevel(level)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLevel(percent) {
|
void setLevel(percent) {
|
||||||
log.debug "Executing 'setLevel'"
|
log.debug "Executing 'setLevel'"
|
||||||
if (verifyPercent(percent)) {
|
if (verifyPercent(percent)) {
|
||||||
parent.setLevel(this, percent)
|
log.trace parent.setLevel(this, percent)
|
||||||
sendEvent(name: "level", value: percent, descriptionText: "Level has changed to ${percent}%")
|
|
||||||
sendEvent(name: "switch", value: "on")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSaturation(percent) {
|
void setSaturation(percent) {
|
||||||
log.debug "Executing 'setSaturation'"
|
log.debug "Executing 'setSaturation'"
|
||||||
if (verifyPercent(percent)) {
|
if (verifyPercent(percent)) {
|
||||||
parent.setSaturation(this, percent)
|
log.trace parent.setSaturation(this, percent)
|
||||||
sendEvent(name: "saturation", value: percent, displayed: false)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setHue(percent) {
|
void setHue(percent) {
|
||||||
log.debug "Executing 'setHue'"
|
log.debug "Executing 'setHue'"
|
||||||
if (verifyPercent(percent)) {
|
if (verifyPercent(percent)) {
|
||||||
parent.setHue(this, percent)
|
log.trace parent.setHue(this, percent)
|
||||||
sendEvent(name: "hue", value: percent, displayed: false)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setColor(value) {
|
void setColor(value) {
|
||||||
log.debug "setColor: ${value}, $this"
|
|
||||||
def events = []
|
def events = []
|
||||||
def validValues = [:]
|
def validValues = [:]
|
||||||
|
|
||||||
if (verifyPercent(value.hue)) {
|
if (verifyPercent(value.hue)) {
|
||||||
events << createEvent(name: "hue", value: value.hue, displayed: false)
|
|
||||||
validValues.hue = value.hue
|
validValues.hue = value.hue
|
||||||
}
|
}
|
||||||
if (verifyPercent(value.saturation)) {
|
if (verifyPercent(value.saturation)) {
|
||||||
events << createEvent(name: "saturation", value: value.saturation, displayed: false)
|
|
||||||
validValues.saturation = value.saturation
|
validValues.saturation = value.saturation
|
||||||
}
|
}
|
||||||
if (value.hex != null) {
|
if (value.hex != null) {
|
||||||
if (value.hex ==~ /^\#([A-Fa-f0-9]){6}$/) {
|
if (value.hex ==~ /^\#([A-Fa-f0-9]){6}$/) {
|
||||||
events << createEvent(name: "color", value: value.hex)
|
|
||||||
validValues.hex = value.hex
|
validValues.hex = value.hex
|
||||||
} else {
|
} else {
|
||||||
log.warn "$value.hex is not a valid color"
|
log.warn "$value.hex is not a valid color"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (verifyPercent(value.level)) {
|
if (verifyPercent(value.level)) {
|
||||||
events << createEvent(name: "level", value: value.level, descriptionText: "Level has changed to ${value.level}%")
|
|
||||||
validValues.level = value.level
|
validValues.level = value.level
|
||||||
}
|
}
|
||||||
if (value.switch == "off" || (value.level != null && value.level <= 0)) {
|
if (value.switch == "off" || (value.level != null && value.level <= 0)) {
|
||||||
events << createEvent(name: "switch", value: "off")
|
|
||||||
validValues.switch = "off"
|
validValues.switch = "off"
|
||||||
} else {
|
} else {
|
||||||
events << createEvent(name: "switch", value: "on")
|
|
||||||
validValues.switch = "on"
|
validValues.switch = "on"
|
||||||
}
|
}
|
||||||
if (!events.isEmpty()) {
|
if (!validValues.isEmpty()) {
|
||||||
parent.setColor(this, validValues)
|
log.trace parent.setColor(this, validValues)
|
||||||
}
|
|
||||||
events.each {
|
|
||||||
sendEvent(it)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
log.debug "Executing 'reset'"
|
log.debug "Executing 'reset'"
|
||||||
def value = [level:100, saturation:56, hue:23]
|
setColorTemperature(4000)
|
||||||
setAdjustedColor(value)
|
|
||||||
parent.poll()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setAdjustedColor(value) {
|
void setAdjustedColor(value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
log.trace "setAdjustedColor: ${value}"
|
log.trace "setAdjustedColor: ${value}"
|
||||||
def adjusted = value + [:]
|
def adjusted = value + [:]
|
||||||
adjusted.hue = adjustOutgoingHue(value.hue)
|
|
||||||
// Needed because color picker always sends 100
|
// Needed because color picker always sends 100
|
||||||
adjusted.level = null
|
adjusted.level = null
|
||||||
setColor(adjusted)
|
setColor(adjusted)
|
||||||
} else {
|
} else {
|
||||||
log.warn "Invalid color input"
|
log.warn "Invalid color input $value"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setColorTemperature(value) {
|
void setColorTemperature(value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
log.trace "setColorTemperature: ${value}k"
|
log.trace "setColorTemperature: ${value}k"
|
||||||
parent.setColorTemperature(this, value)
|
log.trace parent.setColorTemperature(this, value)
|
||||||
sendEvent(name: "colorTemperature", value: value)
|
|
||||||
sendEvent(name: "switch", value: "on")
|
|
||||||
} else {
|
} else {
|
||||||
log.warn "Invalid color temperature"
|
log.warn "Invalid color temperature $value"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,23 +172,6 @@ void refresh() {
|
|||||||
parent.manualRefresh()
|
parent.manualRefresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
def adjustOutgoingHue(percent) {
|
|
||||||
def adjusted = percent
|
|
||||||
if (percent > 31) {
|
|
||||||
if (percent < 63.0) {
|
|
||||||
adjusted = percent + (7 * (percent -30 ) / 32)
|
|
||||||
}
|
|
||||||
else if (percent < 73.0) {
|
|
||||||
adjusted = 69 + (5 * (percent - 62) / 10)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
adjusted = percent + (2 * (100 - percent) / 28)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.info "percent: $percent, adjusted: $adjusted"
|
|
||||||
adjusted
|
|
||||||
}
|
|
||||||
|
|
||||||
def verifyPercent(percent) {
|
def verifyPercent(percent) {
|
||||||
if (percent == null)
|
if (percent == null)
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -68,20 +68,16 @@ def parse(description) {
|
|||||||
// handle commands
|
// handle commands
|
||||||
void on() {
|
void on() {
|
||||||
log.trace parent.on(this)
|
log.trace parent.on(this)
|
||||||
sendEvent(name: "switch", value: "on")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void off() {
|
void off() {
|
||||||
log.trace parent.off(this)
|
log.trace parent.off(this)
|
||||||
sendEvent(name: "switch", value: "off")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLevel(percent) {
|
void setLevel(percent) {
|
||||||
log.debug "Executing 'setLevel'"
|
log.debug "Executing 'setLevel'"
|
||||||
if (percent != null && percent >= 0 && percent <= 100) {
|
if (percent != null && percent >= 0 && percent <= 100) {
|
||||||
parent.setLevel(this, percent)
|
parent.setLevel(this, percent)
|
||||||
sendEvent(name: "level", value: percent)
|
|
||||||
sendEvent(name: "switch", value: "on")
|
|
||||||
} else {
|
} else {
|
||||||
log.warn "$percent is not 0-100"
|
log.warn "$percent is not 0-100"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,12 +36,12 @@ metadata {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2000..6500)") {
|
controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2200..6500)") {
|
||||||
state "colorTemperature", action:"color temperature.setColorTemperature"
|
state "colorTemperature", action:"color temperature.setColorTemperature"
|
||||||
}
|
}
|
||||||
|
|
||||||
valueTile("colorTemp", "device.colorTemperature", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
|
valueTile("colorTemp", "device.colorTemperature", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
|
||||||
state "colorTemperature", label: '${currentValue} K'
|
state "colorTemperature", label: 'WHITES'
|
||||||
}
|
}
|
||||||
|
|
||||||
standardTile("refresh", "device.refresh", height: 2, width: 2, inactiveLabel: false, decoration: "flat") {
|
standardTile("refresh", "device.refresh", height: 2, width: 2, inactiveLabel: false, decoration: "flat") {
|
||||||
@@ -73,20 +73,16 @@ def parse(description) {
|
|||||||
// handle commands
|
// handle commands
|
||||||
void on() {
|
void on() {
|
||||||
log.trace parent.on(this)
|
log.trace parent.on(this)
|
||||||
sendEvent(name: "switch", value: "on")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void off() {
|
void off() {
|
||||||
log.trace parent.off(this)
|
log.trace parent.off(this)
|
||||||
sendEvent(name: "switch", value: "off")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLevel(percent) {
|
void setLevel(percent) {
|
||||||
log.debug "Executing 'setLevel'"
|
log.debug "Executing 'setLevel'"
|
||||||
if (percent != null && percent >= 0 && percent <= 100) {
|
if (percent != null && percent >= 0 && percent <= 100) {
|
||||||
parent.setLevel(this, percent)
|
log.trace parent.setLevel(this, percent)
|
||||||
sendEvent(name: "level", value: percent)
|
|
||||||
sendEvent(name: "switch", value: "on")
|
|
||||||
} else {
|
} else {
|
||||||
log.warn "$percent is not 0-100"
|
log.warn "$percent is not 0-100"
|
||||||
}
|
}
|
||||||
@@ -95,9 +91,7 @@ void setLevel(percent) {
|
|||||||
void setColorTemperature(value) {
|
void setColorTemperature(value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
log.trace "setColorTemperature: ${value}k"
|
log.trace "setColorTemperature: ${value}k"
|
||||||
parent.setColorTemperature(this, value)
|
log.trace parent.setColorTemperature(this, value)
|
||||||
sendEvent(name: "colorTemperature", value: value)
|
|
||||||
sendEvent(name: "switch", value: "on")
|
|
||||||
} else {
|
} else {
|
||||||
log.warn "Invalid color temperature"
|
log.warn "Invalid color temperature"
|
||||||
}
|
}
|
||||||
@@ -107,4 +101,3 @@ void refresh() {
|
|||||||
log.debug "Executing 'refresh'"
|
log.debug "Executing 'refresh'"
|
||||||
parent.manualRefresh()
|
parent.manualRefresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ metadata {
|
|||||||
capability "Temperature Measurement"
|
capability "Temperature Measurement"
|
||||||
capability "Water Sensor"
|
capability "Water Sensor"
|
||||||
capability "Health Check"
|
capability "Health Check"
|
||||||
|
capability "Sensor"
|
||||||
|
|
||||||
command "enrollResponse"
|
command "enrollResponse"
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ metadata {
|
|||||||
capability "Temperature Measurement"
|
capability "Temperature Measurement"
|
||||||
capability "Refresh"
|
capability "Refresh"
|
||||||
capability "Health Check"
|
capability "Health Check"
|
||||||
|
capability "Sensor"
|
||||||
|
|
||||||
command "enrollResponse"
|
command "enrollResponse"
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
capability "Refresh"
|
capability "Refresh"
|
||||||
capability "Temperature Measurement"
|
capability "Temperature Measurement"
|
||||||
capability "Health Check"
|
capability "Health Check"
|
||||||
|
capability "Sensor"
|
||||||
|
|
||||||
command "enrollResponse"
|
command "enrollResponse"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ metadata {
|
|||||||
capability "Temperature Measurement"
|
capability "Temperature Measurement"
|
||||||
capability "Relative Humidity Measurement"
|
capability "Relative Humidity Measurement"
|
||||||
capability "Health Check"
|
capability "Health Check"
|
||||||
|
capability "Sensor"
|
||||||
|
|
||||||
fingerprint endpointId: "01", inClusters: "0001,0003,0020,0402,0B05,FC45", outClusters: "0019,0003"
|
fingerprint endpointId: "01", inClusters: "0001,0003,0020,0402,0B05,FC45", outClusters: "0019,0003"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
metadata {
|
metadata {
|
||||||
definition (name: "Simulated Alarm", namespace: "smartthings/testing", author: "SmartThings") {
|
definition (name: "Simulated Alarm", namespace: "smartthings/testing", author: "SmartThings") {
|
||||||
capability "Alarm"
|
capability "Alarm"
|
||||||
|
capability "Sensor"
|
||||||
|
capability "Actuator"
|
||||||
}
|
}
|
||||||
|
|
||||||
simulator {
|
simulator {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
metadata {
|
metadata {
|
||||||
definition (name: "Simulated Color Control", namespace: "smartthings/testing", author: "SmartThings") {
|
definition (name: "Simulated Color Control", namespace: "smartthings/testing", author: "SmartThings") {
|
||||||
capability "Color Control"
|
capability "Color Control"
|
||||||
|
capability "Sensor"
|
||||||
|
capability "Actuator"
|
||||||
}
|
}
|
||||||
|
|
||||||
simulator {
|
simulator {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ metadata {
|
|||||||
// Automatically generated. Make future change here.
|
// Automatically generated. Make future change here.
|
||||||
definition (name: "Simulated Contact Sensor", namespace: "smartthings/testing", author: "bob") {
|
definition (name: "Simulated Contact Sensor", namespace: "smartthings/testing", author: "bob") {
|
||||||
capability "Contact Sensor"
|
capability "Contact Sensor"
|
||||||
|
capability "Sensor"
|
||||||
|
|
||||||
command "open"
|
command "open"
|
||||||
command "close"
|
command "close"
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ metadata {
|
|||||||
// Automatically generated. Make future change here.
|
// Automatically generated. Make future change here.
|
||||||
definition (name: "Simulated Lock", namespace: "smartthings/testing", author: "bob") {
|
definition (name: "Simulated Lock", namespace: "smartthings/testing", author: "bob") {
|
||||||
capability "Lock"
|
capability "Lock"
|
||||||
|
capability "Sensor"
|
||||||
|
capability "Actuator"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simulated lock
|
// Simulated lock
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ metadata {
|
|||||||
// Automatically generated. Make future change here.
|
// Automatically generated. Make future change here.
|
||||||
definition (name: "Simulated Motion Sensor", namespace: "smartthings/testing", author: "bob") {
|
definition (name: "Simulated Motion Sensor", namespace: "smartthings/testing", author: "bob") {
|
||||||
capability "Motion Sensor"
|
capability "Motion Sensor"
|
||||||
|
capability "Sensor"
|
||||||
|
|
||||||
command "active"
|
command "active"
|
||||||
command "inactive"
|
command "inactive"
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ metadata {
|
|||||||
// Automatically generated. Make future change here.
|
// Automatically generated. Make future change here.
|
||||||
definition (name: "Simulated Presence Sensor", namespace: "smartthings/testing", author: "bob") {
|
definition (name: "Simulated Presence Sensor", namespace: "smartthings/testing", author: "bob") {
|
||||||
capability "Presence Sensor"
|
capability "Presence Sensor"
|
||||||
|
capability "Sensor"
|
||||||
|
|
||||||
command "arrived"
|
command "arrived"
|
||||||
command "departed"
|
command "departed"
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ metadata {
|
|||||||
definition (name: "Simulated Switch", namespace: "smartthings/testing", author: "bob") {
|
definition (name: "Simulated Switch", namespace: "smartthings/testing", author: "bob") {
|
||||||
capability "Switch"
|
capability "Switch"
|
||||||
capability "Relay Switch"
|
capability "Relay Switch"
|
||||||
|
capability "Sensor"
|
||||||
|
capability "Actuator"
|
||||||
|
|
||||||
command "onPhysical"
|
command "onPhysical"
|
||||||
command "offPhysical"
|
command "offPhysical"
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ metadata {
|
|||||||
definition (name: "Simulated Temperature Sensor", namespace: "smartthings/testing", author: "SmartThings") {
|
definition (name: "Simulated Temperature Sensor", namespace: "smartthings/testing", author: "SmartThings") {
|
||||||
capability "Temperature Measurement"
|
capability "Temperature Measurement"
|
||||||
capability "Switch Level"
|
capability "Switch Level"
|
||||||
|
capability "Sensor"
|
||||||
|
|
||||||
command "up"
|
command "up"
|
||||||
command "down"
|
command "down"
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ metadata {
|
|||||||
definition (name: "Simulated Thermostat", namespace: "smartthings/testing", author: "SmartThings") {
|
definition (name: "Simulated Thermostat", namespace: "smartthings/testing", author: "SmartThings") {
|
||||||
capability "Thermostat"
|
capability "Thermostat"
|
||||||
capability "Relative Humidity Measurement"
|
capability "Relative Humidity Measurement"
|
||||||
|
capability "Sensor"
|
||||||
|
capability "Actuator"
|
||||||
|
|
||||||
command "tempUp"
|
command "tempUp"
|
||||||
command "tempDown"
|
command "tempDown"
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ metadata {
|
|||||||
// Automatically generated. Make future change here.
|
// Automatically generated. Make future change here.
|
||||||
definition (name: "Simulated Water Sensor", namespace: "smartthings/testing", author: "SmartThings") {
|
definition (name: "Simulated Water Sensor", namespace: "smartthings/testing", author: "SmartThings") {
|
||||||
capability "Water Sensor"
|
capability "Water Sensor"
|
||||||
|
capability "Sensor"
|
||||||
|
|
||||||
command "wet"
|
command "wet"
|
||||||
command "dry"
|
command "dry"
|
||||||
|
|||||||
@@ -53,7 +53,10 @@ def parse(String description) {
|
|||||||
|
|
||||||
def event = zigbee.getEvent(description)
|
def event = zigbee.getEvent(description)
|
||||||
if (event) {
|
if (event) {
|
||||||
sendEvent(event)
|
if (event.name=="level" && event.value==0) {}
|
||||||
|
else {
|
||||||
|
sendEvent(event)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log.warn "DID NOT PARSE MESSAGE for description : $description"
|
log.warn "DID NOT PARSE MESSAGE for description : $description"
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ metadata {
|
|||||||
capability "Switch"
|
capability "Switch"
|
||||||
capability "Switch Level"
|
capability "Switch Level"
|
||||||
|
|
||||||
|
attribute "colorName", "string"
|
||||||
|
command "setGenericName"
|
||||||
|
|
||||||
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0300,0B04,FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY Flex RGBW", deviceJoinName: "OSRAM LIGHTIFY LED FLEXIBLE STRIP RGBW"
|
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0300,0B04,FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY Flex RGBW", deviceJoinName: "OSRAM LIGHTIFY LED FLEXIBLE STRIP RGBW"
|
||||||
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0300,0B04,FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "Flex RGBW", deviceJoinName: "OSRAM LIGHTIFY LED FLEXIBLE STRIP RGBW"
|
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0300,0B04,FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "Flex RGBW", deviceJoinName: "OSRAM LIGHTIFY LED FLEXIBLE STRIP RGBW"
|
||||||
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0300,0B04,FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY A19 RGBW", deviceJoinName: "OSRAM LIGHTIFY LED A19 RGBW"
|
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0300,0B04,FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY A19 RGBW", deviceJoinName: "OSRAM LIGHTIFY LED A19 RGBW"
|
||||||
@@ -54,15 +57,15 @@ metadata {
|
|||||||
controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2700..6500)") {
|
controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2700..6500)") {
|
||||||
state "colorTemperature", action:"color temperature.setColorTemperature"
|
state "colorTemperature", action:"color temperature.setColorTemperature"
|
||||||
}
|
}
|
||||||
valueTile("colorTemp", "device.colorTemperature", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
|
valueTile("colorName", "device.colorName", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
|
||||||
state "colorTemperature", label: '${currentValue} K'
|
state "colorName", label: '${currentValue}'
|
||||||
}
|
}
|
||||||
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
|
standardTile("refresh", "device.refresh", 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"])
|
main(["switch"])
|
||||||
details(["switch", "colorTempSliderControl", "colorTemp", "refresh"])
|
details(["switch", "colorTempSliderControl", "colorName", "refresh"])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,10 +81,16 @@ private getATTRIBUTE_COLOR_TEMPERATURE() { 0x0007 }
|
|||||||
def parse(String description) {
|
def parse(String description) {
|
||||||
log.debug "description is $description"
|
log.debug "description is $description"
|
||||||
|
|
||||||
def finalResult = zigbee.getEvent(description)
|
def event = zigbee.getEvent(description)
|
||||||
if (finalResult) {
|
if (event) {
|
||||||
log.debug finalResult
|
log.debug event
|
||||||
sendEvent(finalResult)
|
if (event.name=="level" && event.value==0) {}
|
||||||
|
else {
|
||||||
|
if (event.name=="colorTemperature") {
|
||||||
|
setGenericName(event.value)
|
||||||
|
}
|
||||||
|
sendEvent(event)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
def zigbeeMap = zigbee.parseDescriptionAsMap(description)
|
def zigbeeMap = zigbee.parseDescriptionAsMap(description)
|
||||||
@@ -121,9 +130,27 @@ def configure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def setColorTemperature(value) {
|
def setColorTemperature(value) {
|
||||||
|
setGenericName(value)
|
||||||
zigbee.setColorTemperature(value)
|
zigbee.setColorTemperature(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Naming based on the wiki article here: http://en.wikipedia.org/wiki/Color_temperature
|
||||||
|
def setGenericName(value){
|
||||||
|
if (value != null) {
|
||||||
|
def genericName = "White"
|
||||||
|
if (value < 3300) {
|
||||||
|
genericName = "Soft White"
|
||||||
|
} else if (value < 4150) {
|
||||||
|
genericName = "Moonlight"
|
||||||
|
} else if (value <= 5000) {
|
||||||
|
genericName = "Cool White"
|
||||||
|
} else if (value >= 5000) {
|
||||||
|
genericName = "Daylight"
|
||||||
|
}
|
||||||
|
sendEvent(name: "colorName", value: genericName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def setLevel(value) {
|
def setLevel(value) {
|
||||||
zigbee.setLevel(value)
|
zigbee.setLevel(value)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ metadata {
|
|||||||
capability "Switch"
|
capability "Switch"
|
||||||
|
|
||||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006"
|
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"
|
||||||
}
|
}
|
||||||
|
|
||||||
// simulator metadata
|
// simulator metadata
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright 2015 SmartThings
|
* Copyright 2016 SmartThings
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
* 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:
|
* in compliance with the License. You may obtain a copy of the License at:
|
||||||
@@ -11,100 +11,133 @@
|
|||||||
* for the specific language governing permissions and limitations under the License.
|
* for the specific language governing permissions and limitations under the License.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
* Capabilities
|
|
||||||
* - Battery
|
|
||||||
* - Configuration
|
|
||||||
* - Refresh
|
|
||||||
* - Switch
|
|
||||||
* - Valve
|
|
||||||
*/
|
|
||||||
|
|
||||||
metadata {
|
metadata {
|
||||||
definition (name: "Zigbee Valve", namespace: "smartthings", author: "SmartThings") {
|
definition (name: "ZigBee Valve", namespace: "smartthings", author: "SmartThings") {
|
||||||
capability "Battery"
|
capability "Actuator"
|
||||||
capability "Configuration"
|
capability "Battery"
|
||||||
capability "Refresh"
|
capability "Configuration"
|
||||||
capability "Switch"
|
capability "Power Source"
|
||||||
capability "Valve"
|
capability "Refresh"
|
||||||
|
capability "Valve"
|
||||||
|
|
||||||
fingerprint profileId: "0104", inClusters: "0000,0001,0003,0004,0005,0020,0006,0B02", outClusters: "0003"
|
fingerprint profileId: "0104", inClusters: "0000, 0001, 0003, 0006, 0020, 0B02, FC02", outClusters: "0019", manufacturer: "WAXMAN", model: "leakSMART Water Valve v2.10", deviceJoinName: "leakSMART Valve"
|
||||||
}
|
fingerprint profileId: "0104", inClusters: "0000, 0001, 0003, 0004, 0005, 0006, 0008, 000F, 0020, 0B02", outClusters: "0003, 0019", manufacturer: "WAXMAN", model: "House Water Valve - MDL-TBD", deviceJoinName: "Waxman House Water Valve"
|
||||||
|
}
|
||||||
|
|
||||||
// simulator metadata
|
// simulator metadata
|
||||||
simulator {
|
simulator {
|
||||||
// status messages
|
// status messages
|
||||||
status "on": "on/off: 1"
|
status "on": "on/off: 1"
|
||||||
status "off": "on/off: 0"
|
status "off": "on/off: 0"
|
||||||
|
|
||||||
// reply messages
|
// reply messages
|
||||||
reply "zcl on-off on": "on/off: 1"
|
reply "zcl on-off on": "on/off: 1"
|
||||||
reply "zcl on-off off": "on/off: 0"
|
reply "zcl on-off off": "on/off: 0"
|
||||||
}
|
}
|
||||||
|
|
||||||
// UI tile definitions
|
tiles(scale: 2) {
|
||||||
tiles {
|
multiAttributeTile(name:"valve", type: "generic", width: 6, height: 4, canChangeIcon: true){
|
||||||
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
|
tileAttribute ("device.contact", key: "PRIMARY_CONTROL") {
|
||||||
state "off", label: 'closed', action: "switch.on", icon: "st.Outdoor.outdoor16", backgroundColor: "#e86d13"
|
attributeState "open", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#53a7c0", nextState:"closing"
|
||||||
state "on", label: 'open', action: "switch.off", icon: "st.Outdoor.outdoor16", backgroundColor: "#53a7c0"
|
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"
|
||||||
main "switch"
|
attributeState "closing", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#e86d13", nextState:"opening"
|
||||||
details(["switch"])
|
}
|
||||||
}
|
tileAttribute ("powerSource", key: "SECONDARY_CONTROL") {
|
||||||
|
attributeState "powerSource", label:'Power Source: ${currentValue}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
valueTile("battery", "device.battery", inactiveLabel:false, decoration:"flat", width:2, height:2) {
|
||||||
|
state "battery", label:'${currentValue}% battery', unit:""
|
||||||
|
}
|
||||||
|
|
||||||
|
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
|
||||||
|
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
|
||||||
|
}
|
||||||
|
|
||||||
|
main(["valve"])
|
||||||
|
details(["valve", "battery", "refresh"])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// Parse incoming device messages to generate events
|
||||||
def parse(String description) {
|
def parse(String description) {
|
||||||
log.info description
|
log.debug "description is $description"
|
||||||
if (description?.startsWith("catchall:")) {
|
def event = zigbee.getEvent(description)
|
||||||
def value = name == "switch" ? (description?.endsWith(" 1") ? "on" : "off") : null
|
if (event) {
|
||||||
def result = createEvent(name: name, value: value)
|
if(event.name == "switch") {
|
||||||
def msg = zigbee.parse(description)
|
event.name = "contact" //0006 cluster in valve is tied to contact
|
||||||
log.debug "Parse returned ${result?.descriptionText}"
|
if(event.value == "on") {
|
||||||
return result
|
event.value = "open"
|
||||||
log.trace msg
|
}
|
||||||
log.trace "data: $msg.data"
|
else if(event.value == "off") {
|
||||||
}
|
event.value = "closed"
|
||||||
else {
|
}
|
||||||
def name = description?.startsWith("on/off: ") ? "switch" : null
|
}
|
||||||
def value = name == "switch" ? (description?.endsWith(" 1") ? "on" : "off") : null
|
sendEvent(event)
|
||||||
def result = createEvent(name: name, value: value)
|
}
|
||||||
log.debug "Parse returned ${result?.descriptionText}"
|
else {
|
||||||
return result
|
def descMap = zigbee.parseDescriptionAsMap(description)
|
||||||
}
|
if (descMap.clusterInt == CLUSTER_BASIC && descMap.attrInt == BASIC_ATTR_POWER_SOURCE){
|
||||||
}
|
def value = descMap.value
|
||||||
|
if (value == "01" || value == "02") {
|
||||||
// Commands to device
|
sendEvent(name: "powerSource", value: "Mains")
|
||||||
def on() {
|
}
|
||||||
log.debug "on()"
|
else if (value == "03") {
|
||||||
sendEvent(name: "switch", value: "on")
|
sendEvent(name: "powerSource", value: "Battery")
|
||||||
"st cmd 0x${device.deviceNetworkId} 1 6 1 {}"
|
}
|
||||||
}
|
else if (value == "04") {
|
||||||
|
sendEvent(name: "powerSource", value: "DC")
|
||||||
def off() {
|
}
|
||||||
log.debug "off()"
|
else {
|
||||||
sendEvent(name: "switch", value: "off")
|
sendEvent(name: "powerSource", value: "Unknown")
|
||||||
"st cmd 0x${device.deviceNetworkId} 1 6 0 {}"
|
}
|
||||||
|
}
|
||||||
|
else if (descMap.clusterInt == CLUSTER_POWER && descMap.attrInt == POWER_ATTR_BATTERY_PERCENTAGE_REMAINING) {
|
||||||
|
event.name = "battery"
|
||||||
|
event.value = Math.round(Integer.parseInt(descMap.value, 16) / 2)
|
||||||
|
sendEvent(event)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log.warn "DID NOT PARSE MESSAGE for description : $description"
|
||||||
|
log.debug descMap
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def open() {
|
def open() {
|
||||||
log.debug "on()"
|
zigbee.on()
|
||||||
sendEvent(name: "switch", value: "on")
|
|
||||||
"st cmd 0x${device.deviceNetworkId} 1 6 1 {}"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def close() {
|
def close() {
|
||||||
log.debug "off()"
|
zigbee.off()
|
||||||
sendEvent(name: "switch", value: "off")
|
|
||||||
"st cmd 0x${device.deviceNetworkId} 1 6 0 {}"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def refresh() {
|
def refresh() {
|
||||||
log.debug "sending refresh command"
|
log.debug "refresh called"
|
||||||
"st rattr 0x${device.deviceNetworkId} 1 6 0"
|
zigbee.onOffRefresh() +
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
def configure() {
|
def configure() {
|
||||||
|
log.debug "Configuring Reporting and Bindings."
|
||||||
"zdo bind 0x${device.deviceNetworkId} 1 1 6 {${device.zigbeeId}} {}"
|
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.onOffRefresh() +
|
||||||
|
zigbee.readAttribute(CLUSTER_BASIC, BASIC_ATTR_POWER_SOURCE) +
|
||||||
|
zigbee.readAttribute(CLUSTER_POWER, POWER_ATTR_BATTERY_PERCENTAGE_REMAINING)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,9 +49,6 @@ metadata {
|
|||||||
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
|
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
|
||||||
attributeState "level", action:"switch level.setLevel"
|
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) {
|
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
|
||||||
@@ -61,12 +58,12 @@ metadata {
|
|||||||
controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2700..6500)") {
|
controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2700..6500)") {
|
||||||
state "colorTemperature", action:"color temperature.setColorTemperature"
|
state "colorTemperature", action:"color temperature.setColorTemperature"
|
||||||
}
|
}
|
||||||
valueTile("colorTemp", "device.colorTemperature", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
|
valueTile("colorName", "device.colorName", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
|
||||||
state "colorTemperature", label: '${currentValue} K'
|
state "colorName", label: '${currentValue}'
|
||||||
}
|
}
|
||||||
|
|
||||||
main(["switch"])
|
main(["switch"])
|
||||||
details(["switch", "colorTempSliderControl", "colorTemp", "refresh"])
|
details(["switch", "colorTempSliderControl", "colorName", "refresh"])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +72,13 @@ def parse(String description) {
|
|||||||
log.debug "description is $description"
|
log.debug "description is $description"
|
||||||
def event = zigbee.getEvent(description)
|
def event = zigbee.getEvent(description)
|
||||||
if (event) {
|
if (event) {
|
||||||
sendEvent(event)
|
if (event.name=="level" && event.value==0) {}
|
||||||
|
else {
|
||||||
|
if (event.name=="colorTemperature") {
|
||||||
|
setGenericName(event.value)
|
||||||
|
}
|
||||||
|
sendEvent(event)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log.warn "DID NOT PARSE MESSAGE for description : $description"
|
log.warn "DID NOT PARSE MESSAGE for description : $description"
|
||||||
|
|||||||
@@ -24,17 +24,24 @@ definition(
|
|||||||
iconX3Url: "http://www.gidjit.com/appicon@3x.png",
|
iconX3Url: "http://www.gidjit.com/appicon@3x.png",
|
||||||
oauth: [displayName: "Gidjit", displayLink: "www.gidjit.com"])
|
oauth: [displayName: "Gidjit", displayLink: "www.gidjit.com"])
|
||||||
|
|
||||||
|
preferences(oauthPage: "deviceAuthorization") {
|
||||||
|
// deviceAuthorization page is simply the devices to authorize
|
||||||
|
page(name: "deviceAuthorization", title: "Device Authorization", nextPage: "instructionPage",
|
||||||
|
install: false, uninstall: true) {
|
||||||
|
section ("Allow Gidjit to have access, thereby allowing you to quickly control and monitor your following devices. Privacy Policy can be found at http://priv.gidjit.com/privacy.html") {
|
||||||
|
input "switches", "capability.switch", title: "Control/Monitor your switches", multiple: true, required: false
|
||||||
|
input "thermostats", "capability.thermostat", title: "Control/Monitor your thermostats", multiple: true, required: false
|
||||||
|
input "windowShades", "capability.windowShade", title: "Control/Monitor your window shades", multiple: true, required: false //windowShade
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
preferences {
|
page(name: "instructionPage", title: "Device Discovery", install: true) {
|
||||||
section ("Allow Gidjit to have access, there by allowing you to quickly control and monitor the following devices") {
|
section() {
|
||||||
input "switches", "capability.switch", title: "Control/Monitor your switches", multiple: true, required: false
|
paragraph "Now the process is complete return to the Devices section of the Detected Screen. From there and you can add actions to each of your device panels, including launching SmartThings routines."
|
||||||
input "thermostats", "capability.thermostat", title: "Control/Monitor your thermostats", multiple: true, required: false
|
}
|
||||||
input "windowShades", "capability.windowShade", title: "Control/Monitor your window shades", multiple: true, required: false //windowShade
|
}
|
||||||
//input "bulbs", "capability.colorControl", title: "Control your lights", multiple: true, required: false //windowShade
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mappings {
|
mappings {
|
||||||
path("/structureinfo") {
|
path("/structureinfo") {
|
||||||
action: [
|
action: [
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ def humidityHandler(evt) {
|
|||||||
log.debug "Notification already sent within the last ${deltaMinutes} minutes"
|
log.debug "Notification already sent within the last ${deltaMinutes} minutes"
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
log.debug "Humidity Rose Above ${tooHumid}: sending SMS to $phone1 and activating ${mySwitch}"
|
log.debug "Humidity Rose Above ${tooHumid}: sending SMS and activating ${mySwitch}"
|
||||||
send("${humiditySensor1.label} sensed high humidity level of ${evt.value}")
|
send("${humiditySensor1.label} sensed high humidity level of ${evt.value}")
|
||||||
switch1?.on()
|
switch1?.on()
|
||||||
}
|
}
|
||||||
@@ -91,7 +91,7 @@ def humidityHandler(evt) {
|
|||||||
log.debug "Notification already sent within the last ${deltaMinutes} minutes"
|
log.debug "Notification already sent within the last ${deltaMinutes} minutes"
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
log.debug "Humidity Fell Below ${notHumidEnough}: sending SMS to $phone1 and activating ${mySwitch}"
|
log.debug "Humidity Fell Below ${notHumidEnough}: sending SMS and activating ${mySwitch}"
|
||||||
send("${humiditySensor1.label} sensed high humidity level of ${evt.value}")
|
send("${humiditySensor1.label} sensed high humidity level of ${evt.value}")
|
||||||
switch1?.off()
|
switch1?.off()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,15 +25,11 @@ preferences {
|
|||||||
|
|
||||||
def installed() {
|
def installed() {
|
||||||
subscribe(contact1, "contact", contactHandler)
|
subscribe(contact1, "contact", contactHandler)
|
||||||
subscribe(switch1, "switch.on", switchOnHandler)
|
|
||||||
subscribe(switch1, "switch.off", switchOffHandler)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def updated() {
|
def updated() {
|
||||||
unsubscribe()
|
unsubscribe()
|
||||||
subscribe(contact1, "contact", contactHandler)
|
subscribe(contact1, "contact", contactHandler)
|
||||||
subscribe(switch1, "switch.on", switchOnHandler)
|
|
||||||
subscribe(switch1, "switch.off", switchOffHandler)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def contactHandler(evt) {
|
def contactHandler(evt) {
|
||||||
@@ -46,4 +42,4 @@ def contactHandler(evt) {
|
|||||||
if (evt.value == "closed") {
|
if (evt.value == "closed") {
|
||||||
if(state.wasOn)switch1.on()
|
if(state.wasOn)switch1.on()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ def humidityHandler(evt) {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (state.lastStatus != "off") {
|
if (state.lastStatus != "off") {
|
||||||
log.debug "Humidity Rose Above $humidityHigh1: sending SMS to $phone1 and deactivating $mySwitch"
|
log.debug "Humidity Rose Above $humidityHigh1: sending SMS and deactivating $mySwitch"
|
||||||
send("${humiditySensor1.label} sensed high humidity level of ${evt.value}, turning off ${switch1.label}")
|
send("${humiditySensor1.label} sensed high humidity level of ${evt.value}, turning off ${switch1.label}")
|
||||||
switch1?.off()
|
switch1?.off()
|
||||||
state.lastStatus = "off"
|
state.lastStatus = "off"
|
||||||
@@ -99,7 +99,7 @@ def humidityHandler(evt) {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (state.lastStatus != "on") {
|
if (state.lastStatus != "on") {
|
||||||
log.debug "Humidity Dropped Below $humidityLow1: sending SMS to $phone1 and activating $mySwitch"
|
log.debug "Humidity Dropped Below $humidityLow1: sending SMS and activating $mySwitch"
|
||||||
send("${humiditySensor1.label} sensed low humidity level of ${evt.value}, turning on ${switch1.label}")
|
send("${humiditySensor1.label} sensed low humidity level of ${evt.value}, turning on ${switch1.label}")
|
||||||
switch1?.on()
|
switch1?.on()
|
||||||
state.lastStatus = "on"
|
state.lastStatus = "on"
|
||||||
@@ -125,4 +125,4 @@ private send(msg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.debug msg
|
log.debug msg
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ def scheduleCheck()
|
|||||||
sendNotificationToContacts("No one has fed the dog", recipients)
|
sendNotificationToContacts("No one has fed the dog", recipients)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log.debug "Feeder was not opened since $midnight, texting $phone1"
|
log.debug "Feeder was not opened since $midnight, texting one phone number"
|
||||||
sendSms(phone1, "No one has fed the dog")
|
sendSms(phone1, "No one has fed the dog")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -69,10 +69,10 @@ def temperatureHandler(evt) {
|
|||||||
def alreadySentSms = recentEvents.count { it.doubleValue <= tooCold } > 1
|
def alreadySentSms = recentEvents.count { it.doubleValue <= tooCold } > 1
|
||||||
|
|
||||||
if (alreadySentSms) {
|
if (alreadySentSms) {
|
||||||
log.debug "SMS already sent to $phone1 within the last $deltaMinutes minutes"
|
log.debug "SMS already sent within the last $deltaMinutes minutes"
|
||||||
// TODO: Send "Temperature back to normal" SMS, turn switch off
|
// TODO: Send "Temperature back to normal" SMS, turn switch off
|
||||||
} else {
|
} else {
|
||||||
log.debug "Temperature dropped below $tooCold: sending SMS to $phone1 and activating $mySwitch"
|
log.debug "Temperature dropped below $tooCold: sending SMS and activating $mySwitch"
|
||||||
def tempScale = location.temperatureScale ?: "F"
|
def tempScale = location.temperatureScale ?: "F"
|
||||||
send("${temperatureSensor1.displayName} is too cold, reporting a temperature of ${evt.value}${evt.unit?:tempScale}")
|
send("${temperatureSensor1.displayName} is too cold, reporting a temperature of ${evt.value}${evt.unit?:tempScale}")
|
||||||
switch1?.on()
|
switch1?.on()
|
||||||
|
|||||||
Reference in New Issue
Block a user