mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-03-08 21:02:56 +00:00
Merge pull request #1439 from SmartThingsCommunity/staging
Rolling up staging to production for deploy
This commit is contained in:
@@ -11,9 +11,9 @@ metadata {
|
||||
capability "Color Temperature"
|
||||
capability "Switch"
|
||||
capability "Switch Level" // brightness
|
||||
capability "Polling"
|
||||
capability "Refresh"
|
||||
capability "Sensor"
|
||||
capability "Health Check"
|
||||
}
|
||||
|
||||
simulator {
|
||||
@@ -23,7 +23,6 @@ metadata {
|
||||
tiles(scale: 2) {
|
||||
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
|
||||
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
|
||||
attributeState "unreachable", label: "?", action:"refresh.refresh", icon:"http://hosted.lifx.co/smartthings/v1/196xUnreachable.png", backgroundColor:"#666666"
|
||||
attributeState "on", label:'${name}', action:"switch.off", icon:"http://hosted.lifx.co/smartthings/v1/196xOn.png", backgroundColor:"#79b821", 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"
|
||||
@@ -64,12 +63,8 @@ metadata {
|
||||
}
|
||||
}
|
||||
|
||||
// parse events into attributes
|
||||
def parse(String description) {
|
||||
if (description == 'updated') {
|
||||
return // don't poll when config settings is being updated as it may time out
|
||||
}
|
||||
poll()
|
||||
void installed() {
|
||||
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"cloud\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device?.hub?.hardwareID}\"}")
|
||||
}
|
||||
|
||||
// handle commands
|
||||
@@ -192,14 +187,17 @@ def off() {
|
||||
return []
|
||||
}
|
||||
|
||||
def poll() {
|
||||
log.debug "Executing 'poll' for ${device} ${this} ${device.deviceNetworkId}"
|
||||
def refresh() {
|
||||
log.debug "Executing 'refresh'"
|
||||
|
||||
def resp = parent.apiGET("/lights/${selector()}")
|
||||
if (resp.status == 404) {
|
||||
sendEvent(name: "switch", value: "unreachable")
|
||||
state.online = false
|
||||
sendEvent(name: "DeviceWatch-DeviceStatusUpdate", value: "offline", displayed: false)
|
||||
log.warn "$device is Offline"
|
||||
return []
|
||||
} else if (resp.status != 200) {
|
||||
log.error("Unexpected result in poll(): [${resp.status}] ${resp.data}")
|
||||
log.error("Unexpected result in refresh(): [${resp.status}] ${resp.data}")
|
||||
return []
|
||||
}
|
||||
def data = resp.data[0]
|
||||
@@ -208,19 +206,20 @@ def poll() {
|
||||
sendEvent(name: "label", value: data.label)
|
||||
sendEvent(name: "level", value: Math.round((data.brightness ?: 1) * 100))
|
||||
sendEvent(name: "switch.setLevel", value: Math.round((data.brightness ?: 1) * 100))
|
||||
sendEvent(name: "switch", value: data.connected ? data.power : "unreachable")
|
||||
sendEvent(name: "switch", value: data.power)
|
||||
sendEvent(name: "color", value: colorUtil.hslToHex((data.color.hue / 3.6) as int, (data.color.saturation * 100) as int))
|
||||
sendEvent(name: "hue", value: data.color.hue / 3.6)
|
||||
sendEvent(name: "saturation", value: data.color.saturation * 100)
|
||||
sendEvent(name: "colorTemperature", value: data.color.kelvin)
|
||||
sendEvent(name: "model", value: "${data.product.company} ${data.product.name}")
|
||||
sendEvent(name: "model", value: data.product.name)
|
||||
|
||||
return []
|
||||
if (data.connected) {
|
||||
sendEvent(name: "DeviceWatch-DeviceStatus", value: "online", displayed: false)
|
||||
log.debug "$device is Online"
|
||||
} else {
|
||||
sendEvent(name: "DeviceWatch-DeviceStatus", value: "offline", displayed: false)
|
||||
log.warn "$device is Offline"
|
||||
}
|
||||
|
||||
def refresh() {
|
||||
log.debug "Executing 'refresh'"
|
||||
poll()
|
||||
}
|
||||
|
||||
def selector() {
|
||||
|
||||
@@ -10,9 +10,9 @@ metadata {
|
||||
capability "Color Temperature"
|
||||
capability "Switch"
|
||||
capability "Switch Level" // brightness
|
||||
capability "Polling"
|
||||
capability "Refresh"
|
||||
capability "Sensor"
|
||||
capability "Health Check"
|
||||
}
|
||||
|
||||
simulator {
|
||||
@@ -22,13 +22,12 @@ metadata {
|
||||
tiles(scale: 2) {
|
||||
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
|
||||
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
|
||||
attributeState "unreachable", label: "?", action:"refresh.refresh", icon:"http://hosted.lifx.co/smartthings/v1/196xUnreachable.png", backgroundColor:"#666666"
|
||||
attributeState "on", label:'${name}', action:"switch.off", icon:"http://hosted.lifx.co/smartthings/v1/196xOn.png", backgroundColor:"#79b821", 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 "turningOff", label:'Turning off', action:"switch.on", icon:"http://hosted.lifx.co/smartthings/v1/196xOff.png", backgroundColor:"#ffffff", nextState:"turningOn"
|
||||
|
||||
}
|
||||
|
||||
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
|
||||
attributeState "level", action:"switch level.setLevel"
|
||||
}
|
||||
@@ -53,15 +52,10 @@ metadata {
|
||||
main "switch"
|
||||
details(["switch", "colorTempSliderControl", "colorTemp", "refresh"])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// parse events into attributes
|
||||
def parse(String description) {
|
||||
if (description == 'updated') {
|
||||
return // don't poll when config settings is being updated as it may time out
|
||||
}
|
||||
poll()
|
||||
void installed() {
|
||||
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"cloud\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device?.hub?.hardwareID}\"}")
|
||||
}
|
||||
|
||||
// handle commands
|
||||
@@ -122,14 +116,17 @@ def off() {
|
||||
return []
|
||||
}
|
||||
|
||||
def poll() {
|
||||
log.debug "Executing 'poll' for ${device} ${this} ${device.deviceNetworkId}"
|
||||
def refresh() {
|
||||
log.debug "Executing 'refresh'"
|
||||
|
||||
def resp = parent.apiGET("/lights/${selector()}")
|
||||
if (resp.status == 404) {
|
||||
sendEvent(name: "switch", value: "unreachable")
|
||||
state.online = false
|
||||
sendEvent(name: "DeviceWatch-DeviceStatusUpdate", value: "offline", displayed: false)
|
||||
log.warn "$device is Offline"
|
||||
return []
|
||||
} else if (resp.status != 200) {
|
||||
log.error("Unexpected result in poll(): [${resp.status}] ${resp.data}")
|
||||
log.error("Unexpected result in refresh(): [${resp.status}] ${resp.data}")
|
||||
return []
|
||||
}
|
||||
def data = resp.data[0]
|
||||
@@ -137,16 +134,17 @@ def poll() {
|
||||
sendEvent(name: "label", value: data.label)
|
||||
sendEvent(name: "level", value: Math.round((data.brightness ?: 1) * 100))
|
||||
sendEvent(name: "switch.setLevel", value: Math.round((data.brightness ?: 1) * 100))
|
||||
sendEvent(name: "switch", value: data.connected ? data.power : "unreachable")
|
||||
sendEvent(name: "switch", value: data.power)
|
||||
sendEvent(name: "colorTemperature", value: data.color.kelvin)
|
||||
sendEvent(name: "model", value: data.product.name)
|
||||
|
||||
return []
|
||||
if (data.connected) {
|
||||
sendEvent(name: "DeviceWatch-DeviceStatus", value: "online", displayed: false)
|
||||
log.debug "$device is Online"
|
||||
} else {
|
||||
sendEvent(name: "DeviceWatch-DeviceStatus", value: "offline", displayed: false)
|
||||
log.warn "$device is Offline"
|
||||
}
|
||||
|
||||
def refresh() {
|
||||
log.debug "Executing 'refresh'"
|
||||
poll()
|
||||
}
|
||||
|
||||
def selector() {
|
||||
|
||||
@@ -202,48 +202,37 @@ private Map getBatteryResult(rawValue) {
|
||||
log.debug "Battery rawValue = ${rawValue}"
|
||||
def linkText = getLinkText(device)
|
||||
|
||||
def result = [
|
||||
name: 'battery',
|
||||
value: '--',
|
||||
translatable: true
|
||||
]
|
||||
def result = [:]
|
||||
|
||||
def volts = rawValue / 10
|
||||
|
||||
if (rawValue == 0 || rawValue == 255) {}
|
||||
else {
|
||||
if (volts > 3.5) {
|
||||
result.descriptionText = "{{ device.displayName }} battery has too much power: (> 3.5) volts."
|
||||
}
|
||||
else {
|
||||
if (device.getDataValue("manufacturer") == "SmartThings") {
|
||||
volts = rawValue // For the batteryMap to work the key needs to be an int
|
||||
def batteryMap = [28:100, 27:100, 26:100, 25:90, 24:90, 23:70,
|
||||
22:70, 21:50, 20:50, 19:30, 18:30, 17:15, 16:1, 15:0]
|
||||
def minVolts = 15
|
||||
def maxVolts = 28
|
||||
if (!(rawValue == 0 || rawValue == 255)) {
|
||||
result.name = 'battery'
|
||||
result.translatable = true
|
||||
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
|
||||
if (device.getDataValue("manufacturer") == "SmartThings") {
|
||||
volts = rawValue // For the batteryMap to work the key needs to be an int
|
||||
def batteryMap = [28: 100, 27: 100, 26: 100, 25: 90, 24: 90, 23: 70,
|
||||
22: 70, 21: 50, 20: 50, 19: 30, 18: 30, 17: 15, 16: 1, 15: 0]
|
||||
def minVolts = 15
|
||||
def maxVolts = 28
|
||||
|
||||
if (volts < minVolts)
|
||||
volts = minVolts
|
||||
else if (volts > maxVolts)
|
||||
volts = maxVolts
|
||||
def pct = batteryMap[volts]
|
||||
if (pct != null) {
|
||||
result.value = pct
|
||||
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
|
||||
}
|
||||
}
|
||||
else {
|
||||
def minVolts = 2.1
|
||||
def maxVolts = 3.0
|
||||
def pct = (volts - minVolts) / (maxVolts - minVolts)
|
||||
def roundedPct = Math.round(pct * 100)
|
||||
if (roundedPct <= 0)
|
||||
roundedPct = 1
|
||||
result.value = Math.min(100, roundedPct)
|
||||
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
|
||||
}
|
||||
if (volts < minVolts)
|
||||
volts = minVolts
|
||||
else if (volts > maxVolts)
|
||||
volts = maxVolts
|
||||
def pct = batteryMap[volts]
|
||||
result.value = pct
|
||||
} else {
|
||||
def minVolts = 2.1
|
||||
def maxVolts = 3.0
|
||||
def pct = (volts - minVolts) / (maxVolts - minVolts)
|
||||
def roundedPct = Math.round(pct * 100)
|
||||
if (roundedPct <= 0)
|
||||
roundedPct = 1
|
||||
result.value = Math.min(100, roundedPct)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
@@ -220,48 +220,35 @@ private Map getBatteryResult(rawValue) {
|
||||
log.debug "Battery rawValue = ${rawValue}"
|
||||
def linkText = getLinkText(device)
|
||||
|
||||
def result = [
|
||||
name: 'battery',
|
||||
value: '--',
|
||||
translatable: true
|
||||
]
|
||||
def result = [:]
|
||||
|
||||
def volts = rawValue / 10
|
||||
|
||||
if (rawValue == 0 || rawValue == 255) {}
|
||||
else {
|
||||
if (volts > 3.5) {
|
||||
result.descriptionText = "{{ device.displayName }} battery has too much power: (> 3.5) volts."
|
||||
}
|
||||
else {
|
||||
if (device.getDataValue("manufacturer") == "SmartThings") {
|
||||
volts = rawValue // For the batteryMap to work the key needs to be an int
|
||||
def batteryMap = [28:100, 27:100, 26:100, 25:90, 24:90, 23:70,
|
||||
22:70, 21:50, 20:50, 19:30, 18:30, 17:15, 16:1, 15:0]
|
||||
def minVolts = 15
|
||||
def maxVolts = 28
|
||||
if (!(rawValue == 0 || rawValue == 255)) {
|
||||
result.name = 'battery'
|
||||
result.translatable = true
|
||||
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
|
||||
if (device.getDataValue("manufacturer") == "SmartThings") {
|
||||
volts = rawValue // For the batteryMap to work the key needs to be an int
|
||||
def batteryMap = [28: 100, 27: 100, 26: 100, 25: 90, 24: 90, 23: 70,
|
||||
22: 70, 21: 50, 20: 50, 19: 30, 18: 30, 17: 15, 16: 1, 15: 0]
|
||||
def minVolts = 15
|
||||
def maxVolts = 28
|
||||
|
||||
if (volts < minVolts)
|
||||
volts = minVolts
|
||||
else if (volts > maxVolts)
|
||||
volts = maxVolts
|
||||
def pct = batteryMap[volts]
|
||||
if (pct != null) {
|
||||
result.value = pct
|
||||
def value = pct
|
||||
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
|
||||
}
|
||||
}
|
||||
else {
|
||||
def minVolts = 2.1
|
||||
def maxVolts = 3.0
|
||||
def pct = (volts - minVolts) / (maxVolts - minVolts)
|
||||
def roundedPct = Math.round(pct * 100)
|
||||
if (roundedPct <= 0)
|
||||
roundedPct = 1
|
||||
result.value = Math.min(100, roundedPct)
|
||||
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
|
||||
}
|
||||
if (volts < minVolts)
|
||||
volts = minVolts
|
||||
else if (volts > maxVolts)
|
||||
volts = maxVolts
|
||||
def pct = batteryMap[volts]
|
||||
result.value = pct
|
||||
} else {
|
||||
def minVolts = 2.1
|
||||
def maxVolts = 3.0
|
||||
def pct = (volts - minVolts) / (maxVolts - minVolts)
|
||||
def roundedPct = Math.round(pct * 100)
|
||||
if (roundedPct <= 0)
|
||||
roundedPct = 1
|
||||
result.value = Math.min(100, roundedPct)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -205,52 +205,24 @@ def getTemperature(value) {
|
||||
}
|
||||
|
||||
private Map getBatteryResult(rawValue) {
|
||||
log.debug "Battery rawValue = ${rawValue}"
|
||||
log.debug 'Battery'
|
||||
def linkText = getLinkText(device)
|
||||
|
||||
def result = [
|
||||
name: 'battery',
|
||||
value: '--',
|
||||
translatable: true
|
||||
]
|
||||
def result = [:]
|
||||
|
||||
def volts = rawValue / 10
|
||||
|
||||
if (rawValue == 0 || rawValue == 255) {}
|
||||
else {
|
||||
if (volts > 3.5) {
|
||||
result.descriptionText = "{{ device.displayName }} battery has too much power: (> 3.5) volts."
|
||||
}
|
||||
else {
|
||||
if (device.getDataValue("manufacturer") == "SmartThings") {
|
||||
volts = rawValue // For the batteryMap to work the key needs to be an int
|
||||
def batteryMap = [28:100, 27:100, 26:100, 25:90, 24:90, 23:70,
|
||||
22:70, 21:50, 20:50, 19:30, 18:30, 17:15, 16:1, 15:0]
|
||||
def minVolts = 15
|
||||
def maxVolts = 28
|
||||
if (!(rawValue == 0 || rawValue == 255)) {
|
||||
def minVolts = 2.1
|
||||
def maxVolts = 3.0
|
||||
def pct = (volts - minVolts) / (maxVolts - minVolts)
|
||||
def roundedPct = Math.round(pct * 100)
|
||||
if (roundedPct <= 0)
|
||||
roundedPct = 1
|
||||
result.name = 'battery'
|
||||
result.value = Math.min(100, roundedPct)
|
||||
result.descriptionText = "${linkText} battery was ${result.value}%"
|
||||
|
||||
if (volts < minVolts)
|
||||
volts = minVolts
|
||||
else if (volts > maxVolts)
|
||||
volts = maxVolts
|
||||
def pct = batteryMap[volts]
|
||||
if (pct != null) {
|
||||
result.value = pct
|
||||
def value = pct
|
||||
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
|
||||
}
|
||||
}
|
||||
else {
|
||||
def minVolts = 2.1
|
||||
def maxVolts = 3.0
|
||||
def pct = (volts - minVolts) / (maxVolts - minVolts)
|
||||
def roundedPct = Math.round(pct * 100)
|
||||
if (roundedPct <= 0)
|
||||
roundedPct = 1
|
||||
result.value = Math.min(100, roundedPct)
|
||||
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
@@ -281,47 +281,35 @@ def getTemperature(value) {
|
||||
private Map getBatteryResult(rawValue) {
|
||||
log.debug "Battery rawValue = ${rawValue}"
|
||||
|
||||
def result = [
|
||||
name: 'battery',
|
||||
value: '--',
|
||||
translatable: true
|
||||
]
|
||||
def result = [:]
|
||||
|
||||
def volts = rawValue / 10
|
||||
|
||||
if (rawValue == 0 || rawValue == 255) {}
|
||||
else {
|
||||
if (volts > 3.5) {
|
||||
result.descriptionText = "{{ device.displayName }} battery has too much power: (> 3.5) volts."
|
||||
}
|
||||
else {
|
||||
if (device.getDataValue("manufacturer") == "SmartThings") {
|
||||
volts = rawValue // For the batteryMap to work the key needs to be an int
|
||||
def batteryMap = [28:100, 27:100, 26:100, 25:90, 24:90, 23:70,
|
||||
22:70, 21:50, 20:50, 19:30, 18:30, 17:15, 16:1, 15:0]
|
||||
def minVolts = 15
|
||||
def maxVolts = 28
|
||||
if (!(rawValue == 0 || rawValue == 255)) {
|
||||
result.name = 'battery'
|
||||
result.translatable = true
|
||||
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
|
||||
if (device.getDataValue("manufacturer") == "SmartThings") {
|
||||
volts = rawValue // For the batteryMap to work the key needs to be an int
|
||||
def batteryMap = [28: 100, 27: 100, 26: 100, 25: 90, 24: 90, 23: 70,
|
||||
22: 70, 21: 50, 20: 50, 19: 30, 18: 30, 17: 15, 16: 1, 15: 0]
|
||||
def minVolts = 15
|
||||
def maxVolts = 28
|
||||
|
||||
if (volts < minVolts)
|
||||
volts = minVolts
|
||||
else if (volts > maxVolts)
|
||||
volts = maxVolts
|
||||
def pct = batteryMap[volts]
|
||||
if (pct != null) {
|
||||
result.value = pct
|
||||
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
|
||||
}
|
||||
}
|
||||
else {
|
||||
def minVolts = 2.1
|
||||
def maxVolts = 3.0
|
||||
def pct = (volts - minVolts) / (maxVolts - minVolts)
|
||||
def roundedPct = Math.round(pct * 100)
|
||||
if (roundedPct <= 0)
|
||||
roundedPct = 1
|
||||
result.value = Math.min(100, roundedPct)
|
||||
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
|
||||
}
|
||||
if (volts < minVolts)
|
||||
volts = minVolts
|
||||
else if (volts > maxVolts)
|
||||
volts = maxVolts
|
||||
def pct = batteryMap[volts]
|
||||
result.value = pct
|
||||
} else {
|
||||
def minVolts = 2.1
|
||||
def maxVolts = 3.0
|
||||
def pct = (volts - minVolts) / (maxVolts - minVolts)
|
||||
def roundedPct = Math.round(pct * 100)
|
||||
if (roundedPct <= 0)
|
||||
roundedPct = 1
|
||||
result.value = Math.min(100, roundedPct)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -256,50 +256,24 @@ def getTemperature(value) {
|
||||
}
|
||||
|
||||
private Map getBatteryResult(rawValue) {
|
||||
log.debug "Battery rawValue = ${rawValue}"
|
||||
log.debug 'Battery'
|
||||
def linkText = getLinkText(device)
|
||||
|
||||
def result = [
|
||||
name: 'battery',
|
||||
value: '--',
|
||||
translatable: true
|
||||
]
|
||||
def result = [:]
|
||||
|
||||
def volts = rawValue / 10
|
||||
|
||||
if (rawValue == 0 || rawValue == 255) {}
|
||||
else {
|
||||
if (volts > 3.5) {
|
||||
result.descriptionText = "{{ device.displayName }} battery has too much power: (> 3.5) volts."
|
||||
}
|
||||
else {
|
||||
if (device.getDataValue("manufacturer") == "SmartThings") {
|
||||
volts = rawValue // For the batteryMap to work the key needs to be an int
|
||||
def batteryMap = [28:100, 27:100, 26:100, 25:90, 24:90, 23:70,
|
||||
22:70, 21:50, 20:50, 19:30, 18:30, 17:15, 16:1, 15:0]
|
||||
def minVolts = 15
|
||||
def maxVolts = 28
|
||||
if (!(rawValue == 0 || rawValue == 255)) {
|
||||
def minVolts = 2.1
|
||||
def maxVolts = 3.0
|
||||
def pct = (volts - minVolts) / (maxVolts - minVolts)
|
||||
def roundedPct = Math.round(pct * 100)
|
||||
if (roundedPct <= 0)
|
||||
roundedPct = 1
|
||||
result.name = 'battery'
|
||||
result.value = Math.min(100, roundedPct)
|
||||
result.descriptionText = "${linkText} battery was ${result.value}%"
|
||||
|
||||
if (volts < minVolts)
|
||||
volts = minVolts
|
||||
else if (volts > maxVolts)
|
||||
volts = maxVolts
|
||||
def pct = batteryMap[volts]
|
||||
if (pct != null) {
|
||||
result.value = pct
|
||||
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
|
||||
}
|
||||
}
|
||||
else {
|
||||
def minVolts = 2.1
|
||||
def maxVolts = 3.0
|
||||
def pct = (volts - minVolts) / (maxVolts - minVolts)
|
||||
def roundedPct = Math.round(pct * 100)
|
||||
if (roundedPct <= 0)
|
||||
roundedPct = 1
|
||||
result.value = Math.min(100, roundedPct)
|
||||
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
@@ -196,25 +196,19 @@ private Map getBatteryResult(rawValue) {
|
||||
log.debug 'Battery'
|
||||
def linkText = getLinkText(device)
|
||||
|
||||
def result = [
|
||||
name: 'battery'
|
||||
]
|
||||
def result = [:]
|
||||
|
||||
def volts = rawValue / 10
|
||||
def descriptionText
|
||||
if (rawValue == 0 || rawValue == 255) {}
|
||||
else if (volts > 3.5) {
|
||||
result.descriptionText = "${linkText} battery has too much power (${volts} volts)."
|
||||
}
|
||||
else {
|
||||
if (!(rawValue == 0 || rawValue == 255)) {
|
||||
def minVolts = 2.1
|
||||
def maxVolts = 3.0
|
||||
def maxVolts = 3.0
|
||||
def pct = (volts - minVolts) / (maxVolts - minVolts)
|
||||
def roundedPct = Math.round(pct * 100)
|
||||
if (roundedPct <= 0)
|
||||
roundedPct = 1
|
||||
result.value = Math.min(100, roundedPct)
|
||||
result.descriptionText = "${linkText} battery was ${result.value}%"
|
||||
result.name = 'battery'
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
@@ -207,25 +207,20 @@ private Map getBatteryResult(rawValue) {
|
||||
log.debug 'Battery'
|
||||
def linkText = getLinkText(device)
|
||||
|
||||
def result = [
|
||||
name: 'battery'
|
||||
]
|
||||
def result = [:]
|
||||
|
||||
def volts = rawValue / 10
|
||||
def descriptionText
|
||||
if (rawValue == 0 || rawValue == 255) {}
|
||||
else if (volts > 3.5) {
|
||||
result.descriptionText = "${linkText} battery has too much power (${volts} volts)."
|
||||
}
|
||||
else {
|
||||
if (!(rawValue == 0 || rawValue == 255)) {
|
||||
def minVolts = 2.1
|
||||
def maxVolts = 3.0
|
||||
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'
|
||||
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
@@ -181,22 +181,17 @@ private Map getBatteryResult(rawValue) {
|
||||
log.debug 'Battery'
|
||||
def linkText = getLinkText(device)
|
||||
|
||||
def result = [
|
||||
name: 'battery'
|
||||
]
|
||||
def result = [:]
|
||||
|
||||
def volts = rawValue / 10
|
||||
def descriptionText
|
||||
if (volts > 3.5) {
|
||||
result.descriptionText = "${linkText} battery has too much power (${volts} volts)."
|
||||
}
|
||||
else {
|
||||
if (!(rawValue == 0 || rawValue == 255)) {
|
||||
def volts = rawValue / 10
|
||||
def minVolts = 2.1
|
||||
def maxVolts = 3.0
|
||||
def maxVolts = 3.0
|
||||
def pct = (volts - minVolts) / (maxVolts - minVolts)
|
||||
def roundedPct = Math.round(pct * 100)
|
||||
result.value = Math.min(100, roundedPct)
|
||||
result.descriptionText = "${linkText} battery was ${result.value}%"
|
||||
result.name = 'battery'
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
.st-ignore
|
||||
README.md
|
||||
41
devicetypes/smartthings/zigbee-dimmer-power.src/README.md
Normal file
41
devicetypes/smartthings/zigbee-dimmer-power.src/README.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# GE Plug-In/In-Wall Smart Dimmer (ZigBee)
|
||||
|
||||
|
||||
|
||||
Works with:
|
||||
|
||||
* [GE In-Wall Smart Dimmer (ZigBee)](https://shop.smartthings.com/#!/products/ge-in-wall-smart-dimmer-switch)
|
||||
* [GE Plug-In Smart Dimmer (ZigBee)](https://www.smartthings.com/works-with-smartthings/ge/ge-plug-in-smart-dimmer-zigbee)
|
||||
|
||||
## Table of contents
|
||||
|
||||
* [Capabilities](#capabilities)
|
||||
* [Health](#device-health)
|
||||
* [Troubleshooting](#Troubleshooting)
|
||||
|
||||
## Capabilities
|
||||
|
||||
* **Actuator** - represents that a Device has commands
|
||||
* **Configuration** - _configure()_ command called when device is installed or device preferences updated
|
||||
* **Refresh** - _refresh()_ command for status updates
|
||||
* **Power Meter** - ability to check the power meter(energy consumption) of device
|
||||
* **Sensor** - represents the device sensor capability
|
||||
* **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
|
||||
|
||||
## Device Health
|
||||
|
||||
A Zigbee dimmer with maxReportTime of 5 mins.
|
||||
Check-in interval is double the value of maxReportTime.
|
||||
This gives the device twice the amount of time to respond before it is marked as offline.
|
||||
Enrolls with default periodic reporting until newer 5 min interval is confirmed
|
||||
It then enrolls the device with updated checkInterval i.e. 12 mins
|
||||
|
||||
## 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:
|
||||
* [GE Z-Wave In-Wall Smart Dimmer (GE 45857) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/204988564-GE-In-Wall-Smart-Dimmer-45857GE-ZigBee-)
|
||||
* [GE Zigbee Plug-in Smart Dimmer (GE 45852) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/205239280-GE-Plug-In-Smart-Dimmer-45852GE-ZigBee-)
|
||||
@@ -21,6 +21,7 @@ metadata {
|
||||
capability "Sensor"
|
||||
capability "Switch"
|
||||
capability "Switch Level"
|
||||
capability "Health Check"
|
||||
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0B04"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0702"
|
||||
@@ -70,8 +71,20 @@ def parse(String description) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
log.warn "DID NOT PARSE MESSAGE for description : $description"
|
||||
log.debug zigbee.parseDescriptionAsMap(description)
|
||||
def cluster = zigbee.parse(description)
|
||||
if (cluster && cluster.clusterId == 0x0006 && cluster.command == 0x07) {
|
||||
if (cluster.data[0] == 0x00){
|
||||
log.debug "ON/OFF REPORTING CONFIG RESPONSE: " + cluster
|
||||
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
||||
}
|
||||
else {
|
||||
log.warn "ON/OFF REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
|
||||
}
|
||||
}
|
||||
else {
|
||||
log.warn "DID NOT PARSE MESSAGE for description : $description"
|
||||
log.debug zigbee.parseDescriptionAsMap(description)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,11 +100,22 @@ def setLevel(value) {
|
||||
zigbee.setLevel(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* PING is used by Device-Watch in attempt to reach the Device
|
||||
* */
|
||||
def ping() {
|
||||
return zigbee.onOffRefresh()
|
||||
}
|
||||
|
||||
def refresh() {
|
||||
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.simpleMeteringPowerRefresh() + zigbee.electricMeasurementPowerRefresh() + zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.simpleMeteringPowerConfig() + zigbee.electricMeasurementPowerConfig()
|
||||
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.simpleMeteringPowerRefresh() + zigbee.electricMeasurementPowerRefresh() + zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.simpleMeteringPowerConfig() + zigbee.electricMeasurementPowerConfig()
|
||||
}
|
||||
|
||||
def configure() {
|
||||
log.debug "Configuring Reporting and Bindings."
|
||||
|
||||
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
|
||||
// enrolls with default periodic reporting until newer 5 min interval is confirmed
|
||||
sendEvent(name: "checkInterval", value: 3 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
||||
refresh()
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ metadata {
|
||||
capability "Power Meter"
|
||||
capability "Sensor"
|
||||
capability "Switch"
|
||||
capability "Health Check"
|
||||
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0B04"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0702"
|
||||
@@ -77,10 +78,28 @@ def on() {
|
||||
}
|
||||
|
||||
def refresh() {
|
||||
zigbee.onOffRefresh() + zigbee.simpleMeteringPowerRefresh() + zigbee.electricMeasurementPowerRefresh() + zigbee.onOffConfig() + zigbee.simpleMeteringPowerConfig() + zigbee.electricMeasurementPowerConfig()
|
||||
Integer reportIntervalMinutes = 5
|
||||
zigbee.onOffRefresh() + zigbee.simpleMeteringPowerRefresh() + zigbee.electricMeasurementPowerRefresh() + zigbee.onOffConfig(0,reportIntervalMinutes * 60) + zigbee.simpleMeteringPowerConfig() + zigbee.electricMeasurementPowerConfig()
|
||||
}
|
||||
|
||||
def configure() {
|
||||
log.debug "Configuring Reporting and Bindings."
|
||||
refresh()
|
||||
log.debug "in configure()"
|
||||
return configureHealthCheck()
|
||||
}
|
||||
|
||||
def configureHealthCheck() {
|
||||
Integer hcIntervalMinutes = 12
|
||||
sendEvent(name: "checkInterval", value: hcIntervalMinutes * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
||||
return refresh()
|
||||
}
|
||||
|
||||
def updated() {
|
||||
log.debug "in updated()"
|
||||
// updated() doesn't have it's return value processed as hub commands, so we have to send them explicitly
|
||||
def cmds = configureHealthCheck()
|
||||
cmds.each{ sendHubCommand(new physicalgraph.device.HubAction(it)) }
|
||||
}
|
||||
|
||||
def ping() {
|
||||
return zigbee.onOffRefresh()
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ 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"
|
||||
}
|
||||
|
||||
// simulator metadata
|
||||
|
||||
@@ -242,8 +242,6 @@ def installed() {
|
||||
} else {
|
||||
initialize()
|
||||
}
|
||||
// Check for new devices and remove old ones every 3 hours
|
||||
runEvery3Hours('updateDevices')
|
||||
}
|
||||
|
||||
// called after settings are changed
|
||||
@@ -271,9 +269,19 @@ private removeChildDevices(devices) {
|
||||
def initialize() {
|
||||
log.debug "initialize"
|
||||
updateDevices()
|
||||
// Check for new devices and remove old ones every 3 hours
|
||||
runEvery5Minutes('updateDevices')
|
||||
setupDeviceWatch()
|
||||
}
|
||||
|
||||
// Misc
|
||||
private setupDeviceWatch() {
|
||||
def hub = location.hubs[0]
|
||||
// Make sure that all child devices are enrolled in device watch
|
||||
getChildDevices().each {
|
||||
it.sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${hub?.hub?.hardwareID}\"}")
|
||||
}
|
||||
}
|
||||
|
||||
Map apiRequestHeaders() {
|
||||
return ["Authorization": "Bearer ${state.lifxAccessToken}",
|
||||
@@ -373,32 +381,46 @@ def updateDevices() {
|
||||
selectors.add("${device.id}")
|
||||
if (!childDevice) {
|
||||
// log.info("Adding device ${device.id}: ${device.product}")
|
||||
def data = [
|
||||
label: device.label,
|
||||
level: Math.round((device.brightness ?: 1) * 100),
|
||||
switch: device.connected ? device.power : "unreachable",
|
||||
colorTemperature: device.color.kelvin
|
||||
]
|
||||
if (device.product.capabilities.has_color) {
|
||||
data["color"] = colorUtil.hslToHex((device.color.hue / 3.6) as int, (device.color.saturation * 100) as int)
|
||||
data["hue"] = device.color.hue / 3.6
|
||||
data["saturation"] = device.color.saturation * 100
|
||||
childDevice = addChildDevice(app.namespace, "LIFX Color Bulb", device.id, null, data)
|
||||
childDevice = addChildDevice(app.namespace, "LIFX Color Bulb", device.id, null, ["label": device.label, "completedSetup": true])
|
||||
} else {
|
||||
childDevice = addChildDevice(app.namespace, "LIFX White Bulb", device.id, null, data)
|
||||
}
|
||||
childDevice = addChildDevice(app.namespace, "LIFX White Bulb", device.id, null, ["label": device.label, "completedSetup": true])
|
||||
}
|
||||
}
|
||||
|
||||
if (device.product.capabilities.has_color) {
|
||||
childDevice.sendEvent(name: "color", value: colorUtil.hslToHex((device.color.hue / 3.6) as int, (device.color.saturation * 100) as int))
|
||||
childDevice.sendEvent(name: "hue", value: device.color.hue / 3.6)
|
||||
childDevice.sendEvent(name: "saturation", value: device.color.saturation * 100)
|
||||
}
|
||||
childDevice.sendEvent(name: "label", value: device.label)
|
||||
childDevice.sendEvent(name: "level", value: Math.round((device.brightness ?: 1) * 100))
|
||||
childDevice.sendEvent(name: "switch.setLevel", value: Math.round((device.brightness ?: 1) * 100))
|
||||
childDevice.sendEvent(name: "switch", value: device.power)
|
||||
childDevice.sendEvent(name: "colorTemperature", value: device.color.kelvin)
|
||||
childDevice.sendEvent(name: "model", value: device.product.name)
|
||||
|
||||
if (state.devices[device.id] == null) {
|
||||
// State missing, add it and set it to opposite status as current status to provoke event below
|
||||
state.devices[device.id] = [online: !device.connected]
|
||||
}
|
||||
|
||||
if (!state.devices[device.id]?.online && device.connected) {
|
||||
// Device came online after being offline
|
||||
childDevice?.sendEvent(name: "DeviceWatch-DeviceStatus", value: "online", displayed: false)
|
||||
log.debug "$device is back Online"
|
||||
} else if (state.devices[device.id]?.online && !device.connected) {
|
||||
// Device went offline after being online
|
||||
childDevice?.sendEvent(name: "DeviceWatch-DeviceStatus", value: "offline", displayed: false)
|
||||
log.debug "$device went Offline"
|
||||
}
|
||||
state.devices[device.id] = [online: device.connected]
|
||||
}
|
||||
getChildDevices().findAll { !selectors.contains("${it.deviceNetworkId}") }.each {
|
||||
log.info("Deleting ${it.deviceNetworkId}")
|
||||
state.devices[it.deviceNetworkId] = null
|
||||
deleteChildDevice(it.deviceNetworkId)
|
||||
}
|
||||
runIn(1, 'refreshDevices') // Asynchronously refresh devices so we don't block
|
||||
}
|
||||
|
||||
def refreshDevices() {
|
||||
log.info("Refreshing all devices...")
|
||||
getChildDevices().each { device ->
|
||||
device.refresh()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user